File: broadcast.doc

package info (click to toggle)
swi-prolog 8.2.4%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 78,084 kB
  • sloc: ansic: 362,656; perl: 322,276; java: 5,451; cpp: 4,625; sh: 3,047; ruby: 1,594; javascript: 1,509; yacc: 845; xml: 317; makefile: 156; sed: 12; sql: 6
file content (114 lines) | stat: -rw-r--r-- 3,982 bytes parent folder | download | duplicates (7)
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}