1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
\libdoc{broadcast}{Broadcast and receive event notifications}
\index{broadcast}\index{message,service}\index{blackboard}%
\index{agent}\index{daemon}%
The \pllib{broadcast} library was invented to realise GUI applications
consisting of stand-alone components that use the Prolog database for
storing the application data. \Figref{broadcast} illustrates the flow of
information using this design
\postscriptfig[width=0.8\linewidth]{broadcast}{Information-flow using
broadcasting service}
The broadcasting service provides two services. Using the `shout'
service, an unknown number of agents may listen to the message and
act. The broadcaster is not (directly) aware of the implications.
Using the `request' service, listening agents are asked for an answer
one-by-one and the broadcaster is allowed to reject answers using
normal Prolog failure.
Shouting is often used to inform about changes made to a common
database. Other messages can be ``save yourself'' or ``show this''.
Requesting is used to get information while the broadcaster is
not aware who might be able to answer the question. For example
``who is showing $X$?''.
\begin{description}
\predicate{broadcast}{1}{+Term}
Broadcast \arg{Term}. There are no limitations to \arg{Term}, though
being a global service, it is good practice to use a descriptive and
unique principal functor. All associated goals are started and
regardless of their success or failure, broadcast/1 always succeeds.
Exceptions are passed.
\predicate{broadcast_request}{1}{+Term}
Unlike broadcast/1, this predicate stops if an associated goal succeeds.
Backtracking causes it to try other listeners. A broadcast request is
used to fetch information without knowing the identity of the agent
providing it. C.f.\ ``Is there someone who knows the age of John?''
could be asked using
\begin{code}
...,
broadcast_request(age_of('John', Age)),
\end{code}
If there is an agent (\jargon{listener}) that registered an `age-of'
service and knows about the age of `John' this question will be
answered.
\predicate{listen}{2}{+Template, :Goal}
Register a \jargon{listen} channel. Whenever a term unifying
\arg{Template} is broadcasted, call \arg{Goal}. The following example
traps all broadcasted messages as a variable unifies to any message.
It is commonly used to debug usage of the library.
\begin{code}
?- listen(Term, (writeln(Term),fail)).
?- broadcast(hello(world)).
hello(world)
true.
\end{code}
\predicate{listen}{3}{+Listener, +Template, :Goal}
Declare \arg{Listener} as the owner of the channel. Unlike a channel
opened using listen/2, channels that have an owner can terminate the
channel. This is commonly used if an object is listening to broadcast
messages. In the example below we define a `name-item' displaying the
name of an identifier represented by the predicate name_of/2.
\begin{code}
:- pce_begin_class(name_item, text_item).
variable(id, any, get, "Id visualised").
initialise(NI, Id:any) :->
name_of(Id, Name),
send_super(NI, initialise, name, Name,
message(NI, set_name, @arg1)),
send(NI, slot, id, Id),
listen(NI, name_of(Id, Name),
send(NI, selection, Name)).
unlink(NI) :->
unlisten(NI),
send_super(NI, unlink).
set_name(NI, Name:name) :->
get(NI, id, Id),
retractall(name_of(Id, _)),
assert(name_of(Id, Name)),
broadcast(name_of(Id, Name)).
:- pce_end_class.
\end{code}
\predicate{unlisten}{1}{+Listener}
Deregister all entries created with listen/3 whose \arg{Listener}
unify.
\predicate{unlisten}{2}{+Listener, +Template}
Deregister all entries created with listen/3 whose \arg{Listener}
and \arg{Template} unify.
\predicate{unlisten}{3}{+Listener, +Template, :Goal}
Deregister all entries created with listen/3 whose \arg{Listener},
\arg{Template} and \arg{Goal} unify.
\predicate{listening}{3}{?Listener, ?Template, ?Goal}
Examine the current listeners. This predicate is useful for debugging
purposes.
\end{description}
|