-
Notifications
You must be signed in to change notification settings - Fork 0
/
actors.tex
624 lines (516 loc) · 28.3 KB
/
actors.tex
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
%!TEX root = reference.tex
\chapter{Actors}
\label{actors}
\index{actors}
An \q{actor} is an encapsulation of behavior and state that is capable of interacting with other \q{actor}s.\footnote{Actors in \Sr should not be confused with Hewitt actors \cite{agha-hew:87}. Although both Hewitt actors and \Sr actors are a paradigm for distributed computing; \Sr actors are somewhat higher-level in that their primary mode of interaction is based on speech actions. \Sr actors are like actors in a play: they recite lines to each other and are choreographed by the author.} Actors represent a way of expressing multiple loci of computation that can interact and collaborate.
\begin{aside}
From a programming methodology perspective, there is some correspondence between actors and objects in `Object Oriented Programming'. It is useful to view an actor as being an active entity that is responsible for some aspect of the overall problem being addressed in the application.
\end{aside}
The core of actors in \Sr is the interaction protocol that they support. This protocol is based on three \emph{speech actions}: \q{notify} which is used to notify an actor that some event has happened; \q{request} which is used to request an actor to perform an action; and \q{query} which is used to ask an actor a question.
\section{A Chatty actor Example}
\label{talkers}
By way of introduction, we first demonstrate \q{actor}s with a simple scenario -- a `chatty' situation involving two \q{actor}s talking to each other in an endless cycle\footnote{We shall see that the length of the conversation is limited by the available stack depth.} -- illustrated in Figure~\vref{pingPongProg}.
\begin{figure}[htbp]
\begin{center}
\includegraphics[width=0.6\textwidth]{diagrams/PingAndPong.pdf}
\caption{Ping and Pong actors}
\label{pingPongProg}
\end{center}
\end{figure}
Each of \q{ping} and \q{pong} have an \q{ear} by which they `hear' events. This is signaled by their type which is an \q{actor} type that references \q{ear} as an \q{occurrence} of \q{string}s. Program~\vref{chattySchema} shows a \q{type} \q{alias} definition that captures this in a \q{type alias}.
\begin{program}
\begin{alltt}
type talker is alias of actor of \{
ear has type occurrence of string;
\}
\end{alltt}
\caption{Type Schema Used by Chatty \q{actor}s}
\label{chattySchema}
\end{program}
\subsection{Chatty Actor Generator}
\label{chattyGenerator}
Although \q{actor}s are first class values; in many cases it makes sense to use generator functions to construct \q{actor}s. This structural device allows encapsulation of the creation of the \q{actor}. In this scenario the two actors are generated by the generator function shown in Program~\vref{chattyGeneratorProgram}.
\begin{program}
\begin{alltt}
chatty has type (()=>talker)=>talker;
fun chatty(Who) is actor\{
on Msg on ear do\{
logMsg(info,"I heard \$Msg");
notify Who() with "Did you hear [\$Msg]?" on ear;
\};
\end{alltt}
\caption{The \q{chatty} Actor Generator}
\label{chattyGeneratorProgram}
\end{program}
The \q{chatty} generator takes the form of a single argument function that returns an actor. The function's argument is the actor that the chatty actor 'knows about'.
The \q{chatty} actor itself is very simple: it listens to an event on its \q{ear}; and when it perceives one it logs it -- see Section~\vref{logMsg} -- and uses the \q{notify} \ntRef{SpeechAction} to inform its partner that it `heard' something.
There are three kinds of \ntRef{SpeechAction}; however, in this scenario we only use the \q{notify} action.
\begin{aside}
In general, an \q{actor} may learn about other \q{actor}s in a variety of ways -- they may be told explicitly about them in a speech action, they may search for them in a central repository. In this case, we build in to the actor a reference to the conversational partner.
\begin{aside}
Note that the form of this information itself comes in the form of a function. I.e., the argument to the \q{chatty} actor is a zero-argument function whose value is the \q{actor} with whom to continue the conversation. The reason for this shall be explained below.
\end{aside}
\end{aside}
\subsection{Setting up a Scenario}
We construct our scenario by defining two actors -- \q{ping} and \q{pong} -- in terms of the \q{chatty} function. The two actors `bounce' off of each other in a circular interdependent structure. In the scenario, we build in the interdependence by passing each \q{actor} to the other -- in a \ntRef{ThetaEnvironment} -- and making use of \ntRef{MemoFunction}s:
\begin{alltt}
let\{
def ping is memo chatty(pong);
def pong is memo chatty(ping);
\}
\end{alltt}
\begin{aside}
The use of \ntRef{MemoFunction}s allows us to express the cyclic structure of the two actors in conversation without violating the normal rules of evaluation.
\end{aside}
Of course, each of \q{ping} and \q{pong} are functionally identical as they were generated by the same generator function.
\subsection{Starting the Interaction}
In order to start the two actors off, we send one of them a \q{notify} \ntRef{SpeechAction}:
\begin{alltt}
let\{
def ping is memo chatty(pong);
def pong is memo chatty(ping);
\} in \{ notify ping() with "hello" on ear \}
\end{alltt}
Once started, the actors \q{ping} and \q{pong} will notify each other of events in an endless cycle -- although each communication will be larger than the previous:
\begin{alltt}
ping {\rm{}to} pong: hello
pong {\rm{}to} ping: Did you hear [hello]?
ping {\rm{}to} pong: Did you hear [Did you hear [hello]?]?
\ldots
\end{alltt}
An actor wishing to respond to an event uses an \ntRef{EventRule} to `catch' events it is interested in. In the case of these chatty actors, their response is to log the message and echo a response, using the rule:
\begin{alltt}
on Msg on ear do\{
logMsg(info,"I heard \$Msg");
notify Who() with "Did you hear [\$Msg]?" on ear;
\};
\end{alltt}
Speech actions are completed when the `target' \q{actor} has performed its response to the action. In the case of a \q{notify} this means that the responding \q{actor} has triggered all relevant \ntRef{EventRule}s. In this case, that means the log message \emph{and} the \q{notify} to the actor's partner.
\begin{aside}
One side-effect of this is that cycles like the one in this scenario are liable to exhaust the system evaluation stack fairly quickly. This program is destined to terminate with a `StackOverflow' exception.
\end{aside}
\begin{program}
\begin{alltt}
chatty is package\{
import speech;
type talker is alias of actor of \{
ear has type occurrence of string;
\}
chatty has type (()=>talker)=>talker;
fun chatty(Who) is actor\{
on Msg on ear do\{
logMsg(info,"I heard \$Msg");
notify Who() with "Did you hear [\$Msg]?" on ear;
\};
\}
prc main() do \{
let\{
def ping is memo chatty(pong);
def pong is memo chatty(ping);
\} in \{ notify ping() with "hello" on ear \}
\}
\}
\end{alltt}
\caption{The Complete \q{chatty} Actor Scenario}
\label{chattyProgram}
\end{program}
The complete scenario is shown in Program~\vref{chattyProgram}. Note that, in order to use \q{actor}s, it is necessary to import the \q{speech} package.
There are three aspects of \q{actor}s that fit together to complete the picture of programming with actors: the architectural structure of actors, the speech action model for how actors interact with each other, and the various kinds of \ntRef{ActorRules} that implement the behavior behind the actors' interactions. \ntRef{SpeechAction}s are described in Section~\vref{contentLanguage}; \ntRef{ActorRules} are described in Section~\vref{actorRules} and the structure of an \q{actor} is described in Section~\vref{actorStructure}.
\section{Actors' Speech}
\label{contentLanguage}
\index{content language}
\index{speech actions}
\index{actor communication}
\index{asking actors to do things}
\index{querying actors}
\index{performatives}
The interaction between actors is based on the concept of \emph{speech actions} -- `actions' that involve communication between actors.
\begin{aside}
The somewhat anthropomorphic term `speech action' is a reference to \emph{Speech Act Theory}, first promulgated by John L. Austin in \cite{austin:60}. Here, we use the term to refer to any of a standard range of actions involving the communication between \q{actor}s.
\end{aside}
\begin{aside}
Although we refer to the different forms of interaction collectively as speech actions; in fact, syntactically some are \ntRef{Action}s and queries are actually \ntRef{Expression}s.
\end{aside}
A speech action consists of a \emph{performative} and associated \emph{content}. The standard performatives allow one actor to \emph{notify} another actor of an event, to \emph{request} that an actor perform an action and to \emph{query} for the value of an expression.
\begin{figure}[htbp]
\begin{eqnarray*}
\emph{Action}&\arrowplus&\ntRef{NotifySA}\,\choice\,\ntRef{RequestSA}\\
\emph{Expression}&\arrowplus&\ntRef{QuerySA}\\
\ntDef{SpeechAction}&\arrow&\ntRef{NotifySA}\,\choice\,\ntRef{RequestSA}\,\choice\,\ntRef{QuerySA}
\end{eqnarray*}
\caption{Speech Actions}
\label{speechActionFig}
\end{figure}
The content of a speech action is interpreted relative to a \emph{schema}. Each actor has a schema of the particular kinds of events, actions and queries that the actor is capable of responding to. This schema is represented by a \ntRef{TypeInterfaceType} that is an argument of the \ntRef{ActorType}.
\subsection{Actor Type}
\label{actorType}
\index{actors!type of}
\index{type!actor@\q{actor}}
Every \q{actor} has an \ntRef{ActorType} -- which exposes elements that can be accessed via the different \emph{speech actions} as outlined in Section~\vref{contentLanguage}. It also exposes elements that the \q{actor} uses in its speech actions.
As shown in Figure~\vref{actorTypeFig}, an \q{actor} type takes an argument type which must be a \ntRef{TypeInterfaceType} which defines the actor's schema.
\begin{figure}[htbp]
\begin{eqnarray*}
\emph{Type}&\arrowplus&\ntRef{ActorType}\\
\ntDef{ActorType}&\arrow&\q{actor}\ \q{of}\ \ntRef{RecordType}\\
&\choice&\q{concurrent actor}\ \q{of}\ \ntRef{RecordType}
\end{eqnarray*}
\caption{Actor Type}
\label{actorTypeFig}
\end{figure}
There are two forms of \ntRef{ActorType} -- the \q{concurrent} form relates to an actor that executes in an independent task (see Section~\vref{taskExpressions} and Section~\vref{concActor})
\subsection{Notifying Actors}
\label{notify}
\index{speech action!notify}
\index{communicating events to actors}
\index{performatives!notify@\q{notify}}
The \q{notify} speech action `informs' an actor of an event. An event is an occurrence of something that is relevant to someone; in this case the actor being notified.
\begin{figure}[htbp]
\begin{eqnarray*}
\ntDef{NotifySA}&\arrow&\q{notify}\ \ntRef{Expression}\ \q{with}\ \ntRef{Expression}\ \q{on}\ \ntRef{Identifier}
\end{eqnarray*}
\caption{Notify Speech Action}
\label{NotifySAFig}
\end{figure}
\begin{aside}
In terms of speech act theory, a \q{notify} of the form:
\begin{alltt}
notify A with E on C
\end{alltt}
can be considered to be equivalent to:
\begin{alltt}
INFORM(A,Happened(C(E)))
\end{alltt}
where \q{INFORM} is the basic action in speech -- of the talker informing the listener of something -- and \q{Happened} corresponds to a predicate that signifies that some occurrence has happened.
\end{aside}
A \q{notify} action of the form:
\begin{alltt}
notify \emph{Ag} with \emph{Exp} on \emph{Id}
\end{alltt}
has the effect of notifying the specifically identified actor \q{\emph{Ag}} that an event has occurred. Specifically, the event is denoted by the value of \q{\emph{Exp}} and the `channel' it is on is identified by \q{\emph{Id}}.
\begin{aside}
Since events may be coming from multiple sources it is not possible to constrain absolutely the processing order of events. However, since a \ntRef{NotifySA} is blocked until the responding actor has processed it, it \emph{is} required that all events from a given source are processed in the order that they are generated. See Section~\vref{actorTypes}.
\end{aside}
\paragraph{Stream Type}
\label{eventType}
A \q{notify} action requires that there be an appropriate \q{occurrence} type on the responding actor's schema.
\index{occurrence!occurrence type@\q{occurrence} type}
\index{occurrence type@\q{occurrence} type}
\index{type! occurrence@\q{occurrence}}
\begin{figure}[htbp]
\begin{eqnarray*}
\emph{Type}&\arrowplus&\emph{EventType}\\
\emph{EventType}&\arrow&\q{occurrence}\ \q{of}\ \emph{Type}
\end{eqnarray*}
\caption{Event Type}
\label{eventTypeFig}
\end{figure}
\begin{aside}
The \q{occurrence} type is actually a generic type; its argument refers to the type of the element of the \q{occurrence}.
\end{aside}
For example, an \q{actor} that responds to update events about the temperature of a boiler might offer a type signature such as
\begin{alltt}
boilerActor has type actor of \{
temp has type occurrence of float;
\}
\end{alltt}
\begin{aside}
\q{occurrence} types are \emph{only} permitted within an \q{actor} type structure.
\end{aside}
\subsubsection{Type Safety}
For \q{notify} to be type safe, the \emph{responding} actor must declare an appropriate element in its schema; i.e., it must have an \q{occurrence} of the right type for the identified channel:
\begin{prooftree}
\def\defaultHypSeparation{\,}
\AxiomC{\typeprd{E}{A}{\q{actor of}\,O\ \q{where}\ O\,\q{implements}\,\q{\{}\,N\,\q{has type occurrence of}\ T\q{\}}}}
\AxiomC{\typeprd{E}{Evt}{T}}
\BinaryInfC{\typesafe{E}{\q{notify} A \q{with }Evt\ \q{on}\ N}}
\end{prooftree}
\subsection{Querying Actors}
\label{query}
\index{querying actors}
\index{performatives!query@\q{query}}
The \q{query} speech action is used to ask actors questions. A \ntRef{QuerySA} takes the form of an expression that is evaluated `against' the schema of the responding actor's schema.
\begin{figure}[htbp]
\begin{eqnarray*}
\ntDef{QuerySA}&\arrow&\q{query}\ \ntRef{Expression}\ [\ntRef{ExportSelection}]\ \q{with}\ \ntRef{Expression}\\
\ntDef{ExportSelection}&\arrow&\q{'s}\ \ntRef{Identifier}\ [\q{'n}\ \ntRef{Identifier}\,\sequence{'n\,}\ \ntRef{Identifier}\ ]
\end{eqnarray*}
\caption{Actor Query Speech Action}
\label{actorQueryFig}
\end{figure}
Syntactically, a \q{query} takes the form of an \emph{Expression} -- rather than an action. This is because queries have values associated with them -- even though they are actions! The value of the \q{query} expression is the result of evaluating the query in the context of the responding actor.
%\begin{aside}
%In terms of Speech Act Theory, a \q{query} can either be regarded as a primitive performative, or it can be interpreted as an INFORM of a DESIRE to be INFORMED. A query of the form:
%\begin{alltt}
%query A with Exp
%\end{alltt}
%has interpretation:
%\begin{alltt}
%INFORM(A,DESIRES(self,INFORM(VALUE-OF(Exp))))
%\end{alltt}
%where \q{self} refers to the asking entity.
%
%There is additional semantics in a \ntRef{QuerySA} that reflects the fact that the `answer' comes back as part of the original speech action and not as a subsequent speech action.
%\end{aside}
The elements of the actor's schema that are accessed by the query expression are identified explicitly via the \ntRef{ExportSelection}. For example, if an actor has the type:
\begin{alltt}
stocker has type actor of \{
average has type (eventTime,eventTime)=>float;
volume has type (eventTime,eventTime)=>float;
\}
\end{alltt}
then a query of the \q{stocker}'s \q{average} and \q{volume} would look like:
\begin{alltt}
query stocker's average 'n volume with average(34,10)*volume(34,10)
\end{alltt}
\begin{aside}
Only those elements of the actor's schema that are mentioned explicitly in the \ntRef{ExportSelection} will reference the responding actor's schema. All other references are regarded either as local to the query or free -- in effect referencing variables from the caller's context.
\end{aside}
\subsubsection{Type Safety}
An actor's schema is used to validate the type safety of a \q{query} against the actor:
\begin{prooftree}
\def\defaultHypSeparation{\hskip 0pt}
\AxiomC{\typeprd{E}{A}{O\,\q{where}\,O\,\q{implements\{}N\sub1\q{has type}\,T\sub1\sequence{;}N\subn\,\q{has type}\,T\subn\q{\}}}}
\AxiomC{\typeprd{O}{Q}{T\sub{Q}}}
\BinaryInfC{\typeprd{E}{\q{query}\ A\q{'s}\ N\sub1\sequence{'n}N\subn\ \q{with}\ Q}{T\sub{Q}}}
\end{prooftree}
\subsection{Requesting Action from an Actor}
\label{request}
\index{requesting action from an actor}
\index{performatives!request@\q{request}}
A \q{request} denotes a request that an actor perform an \emph{Action}. The assumption is that an \q{actor} may modify its internal state as a result of responding to the \q{request}.
\begin{figure}[htbp]
\begin{eqnarray*}
\emph{RequestSA}&\arrow&\q{request}\ \ntRef{Expression}\ [\ntRef{ExportSelection}]\ \q{to}\ \emph{Action}\\
\end{eqnarray*}
\caption{Request Speech Action}
\label{RequestSAFig}
\end{figure}
Similarly to the \ntRef{QuerySA}, the elements of the actor's schema that are accessed by the \ntRef{Action} -- and any embedded expressions within the \ntRef{Action} -- are identified explicitly via the \ntRef{ExportSelection}. For example, if an actor has the type:
\begin{alltt}
bank has type actor of \{
setBalance has type (float)=>();
currentBalance has type ()=>float;
\}
\end{alltt}
then a request to increase the \q{bank}'s balance by 20\% would look like:
\begin{alltt}
request bank's setBalance 'n currentBalance to
setBalance(currentBalance()*1.2)
\end{alltt}
\begin{aside}
Again, as with \ntRef{QuerySA}, only those elements of the actor's schema that are mentioned explicitly in the \ntRef{ExportSelection} will reference the responding actor's schema. All other references are regarded either as local to the query or free -- in effect referencing variables from the caller's context.
\end{aside}
\subsubsection{Type Safety}
\emph{RequestSA}s do not have a type but, like other actions, must be type-safe.
\begin{prooftree}
\def\defaultHypSeparation{\hskip 0pt}
\AxiomC{\typeprd{E}{A}{O\,\q{where}\,O\,\q{implements\{}N\sub1\q{has type}\,T\sub1\sequence{;}N\subn\,\q{has type}\,T\subn\q{\}}}}
\AxiomC{\typesafe{E}{A}}
\BinaryInfC{\typesafe{E}{\q{request}\ A\q{'s}\ N\sub1\sequence{'n}N\subn\ \q{to}\ A}}
\end{prooftree}
\section{Actor Structure}
\label{actorStructure}
\index{actors!structure of}
An \q{actor} consists of a set of \ntRef{ActorRule}s -- enclosed in an \q{actor\{\ldots\}} structure -- that define how the \q{actor} responds to \ntRef{SpeechAction}s.
\begin{figure}[H]
\begin{eqnarray*}
\ntDef{Actor}&\arrow&\q{actor}\q{\{}\,\ntRef{ActorRule}\sequence{;}\ntRef{ActorRule}\,\q{\}}\\
&\choice&\q{concurrent actor}\q{\{}\,\ntRef{ActorRule}\sequence{;}\ntRef{ActorRule}\,\q{\}}\\
\ntDef{ActorRule}&\arrow&\ntRef{EventRule}\ \choice\,\ntRef{Definition}
\end{eqnarray*}
\caption{Actor Structure}
\label{actorStructureFig}
\end{figure}
Actors are first-class values: they can be bound to variables, passed as arguments to functions and stored in structures. However, as noted in Section~\vref{chattyGenerator}, it is often convenient to arrange for actors to be generated via generator functions.
\begin{aside}
Actors are typically structured into a separate communicative \q{actor} `head' and an active `body' with a \q{using} or \q{let} (see Section~\vref{letExpression}).
The head contains the rules that support the interactions with other actors, and the body contains functionality that defines what the actor can do.
\end{aside}
An example of this is shown in Program~\vref{stockTicker} which defines an actor that keeps information of recent stock trades.\footnote{This should not be construed as an authoritative example of an actor that handles price updates.}
\begin{program}
\begin{alltt}
fun stocker() is actor\{
on (Price,When) on tick do extend prices with (Price,When);
fun average(Frm,To) is valof\{
def Prices is all Pr where (Pr,W) in prices and Frm=<W and W<To;
valis Prices/size(Prices);
\}
prc clear(Frm,To) do delete ((Pr,W) where Frm=<W and W<To) in prices;
\} using \{
prices has type list of ((float,eventTime));
def prices is list of [];
\}
\end{alltt}
\caption{A Stock Actor}
\label{stockTicker}
\end{program}
An \q{actor} may contain \ntRef{EventRule}s to allow it to respond to \q{notify} speech actions; otherwise, any valid \ntRef{Definition} may be present in an \q{actor}.
\subsection{Event Rules}
\label{actorRules}
\index{actors!event rules}
\index{events!rules}
An event rule is a rule that is used to respond to \q{notify} speech actions. An event is an occurrence of something that is `of interest' to an \q{actor}.
\begin{figure}[htbp]
\begin{eqnarray*}
\ntDef{EventRule}&\arrow&\q{on}\ \ntRef{Pattern}\ \q{on}\ \ntRef{Identifier}\ [\,\q{where}\ \ntRef{Condition}\,]\ \q{do}\ \ntRef{Action}
\end{eqnarray*}
\caption{Event Rules}
\label{eventRuleFig}
\end{figure}
\ntRef{EventRule}s have a two part structure: a pattern that matches an event on a particular occurrence and an \ntRef{Action} body. In addition, an \ntRef{EventRule} may have an optional \ntRef{Condition} that must be satisfied before the rule can `fire'.
\index{condition!in event rules}
\index{event rule conditions}
There may be any number of event rules about a given occurrence. All the \ntRef{EventRule}s that apply will fire on receipt of a given \q{notify}.
\subsection{Responding to Requests}
\label{requestResponse}
\index{actor!responding to \q{requests}}
\index{responding to \q{actor} \q{requests}}
\ntRef{RequestSA}s are handled using \ntRef{Procedure}s. The \ntRef{RequestSA} may refer to more than one \ntRef{Procedure}; and may even refer to other functions and variables that are exposed by the \q{actor}. Each `call' within the \ntRef{RequestSA} is fielded by directly calling the appropriate \ntRef{Procedure} or \ntRef{Function} within the actor.
\index{how a request is handled@how a \q{request} is handled}
\index{waiting for requests}
The \q{stocker} actor in Program~\vref{stockTicker} will respond to a \q{clear} \q{request} by removing elements from its memory.
\subsection{Querying an Actor}
\label{actorQuery}
\index{actor!query an}
\index{query!an actor}
Queries to actors are handled simply by evaluating an expression in the context of the \q{actor}. In particular, if the \q{query} is of a \q{list}, then the evaluation will often involve the use of \q{view} definitions.
\section{The Speech Contract}
\label{speechContract}
The foundation of actors in \Sr is the \q{speech} contract that is defined in Program~\vref{speechContractProg}. This contract relies on the \q{result} type -- which is defined in Program~\vref{successTypeProg}.
\begin{program}
\begin{alltt}
type result of t is success(t)
or denied(reason)
or failed(exception);
type reason is busy or noPermission
\end{alltt}
\caption{Success Result Type}
\label{successTypeProg}
\end{program}
\begin{program}
\begin{alltt}
contract speech over t determines (u,a) where execution over a is \{
_query has type for all s such that
(t,(u)=>s,()=>quoted,()=>dictionary of (string,quoted))=> a of s;
_request has type
(t,(u)=>(),()=>quoted,()=>dictionary of (string,quoted)) => a of ()
_notify has type (t,(u)=>()) => a of ();
\};
\end{alltt}
\caption{Speech Contract Used by \q{actor}s}
\label{speechContractProg}
\end{program}
This contract is generally not referenced explicitly by \q{actor}-based programs as \Sr has syntactic features to support \q{actor}s and speech actions. Individual \ntRef{SpeechAction}s are mapped to equivalent calls to \q{\_query}, \q{\_request} or \q{\_notify}.
Speech actions are encoded into calls to the three functions in the \q{speech} contract: a \q{notify} becomes a call to \q{\_notify}, specifically the \q{notify} action:
\begin{alltt}
notify \emph{Ag} with \emph{Event} on \emph{Channel}
\end{alltt}
becomes:
\begin{alltt}
_notify(\emph{Ag}, (AA)=>\emph{Channel}(\emph{Event}))
\end{alltt}
A \q{query} is encoded into a call of \q{\_query} with four arguments. Specifically, the \q{query}:
\begin{alltt}
query \emph{Ag} with \emph{Expression}
\end{alltt}
becomes:
\begin{alltt}
\_query(\emph{Ag}, (AA)=>\emph{Expression}, ()=><|\emph{Expression}|>,
()=> dictionary of ["\emph{F\sub1}"->F\sub1 as quoted\sequence{,}"\emph{F\subn}"->F\subn as quoted\,])
\end{alltt}
where
\begin{alltt}
dictionary of ["\emph{F\sub1}"->F\sub1 as quoted\sequence{,}"\emph{F\subn}"->F\subn as quoted\,]
\end{alltt}
is a dictionary of all the free variables in \emph{Expression} and the expressions of the form
\begin{alltt}
"F\subi"->F\subi as quoted
\end{alltt}
are, in effect, a \emph{serialization} of the value of the free variable as a \q{quoted} value.
The function:
\begin{alltt}
()=><|\emph{Expression}|>
\end{alltt}
can be used by the receiver of the \q{query} if it either does not trust the function or if it needs to transform the query in some way.
A \q{request} speech action has similar processing to the \q{query}. The \q{request}:
\begin{alltt}
request \emph{Ag} to \emph{Act}
\end{alltt}
is translated to the call:
\begin{alltt}
_request(\emph{Ag}, (AA)=>\emph{Act}, ()=><|\emph{Act}|>,
()=>dictionary of ["\emph{F\sub1}"->F\sub1 as quoted\sequence{,}"\emph{F\subn}"->F\subn as quoted\,])
\end{alltt}
with a similar interpretation of the arguments.
Note that references within the \q{query} and \q{request} speech action to elements of the target's interface become dot-references (\ntRef{RecordAccess}) of the form:
\begin{alltt}
AA.foo
\end{alltt}
\section{Different Types of Actor}
\label{actorTypes}
There are two `standard' implementations of actor: a light weight actor that has similar computational characteristics as conventional objects and a concurrent actor which is associated with its own \q{task}.
\subsection{Light Weight Actors}
\label{liteActor}
The simple light weight actor as defined by the \q{actor} type in Program~\vref{actorTypeProg} is essentially a simple wrapper around a \ntRef{RecordType}.
\begin{program}
\begin{alltt}
type actor of t is act0r(t);
\end{alltt}
\caption{Standard Light Weight \q{actor} Type}
\label{actorTypeProg}
\end{program}
The implementation of the speech contract for \q{actor} is shown in Program~\vref{actorSpeechProg}.
\begin{program}
\begin{alltt}
implementation speech over for all t such that actor of t determines t is \{
fun \_query(act0r(Ac),Qf,_,_) is Qf(Ac);
prc \_request(act0r(Ac),Rf,_,_) do Rf(Ac);
prc \_notify(act0r(Ac),Np) do Np(Ac);
\};
\end{alltt}
\caption{Actor's Implementation of the Speech Contract}
\label{actorSpeechProg}
\end{program}
\begin{aside}
What is not shown here is how the internals of \q{actor}s -- in particular \ntRef{EventRule}s -- are implemented.
\end{aside}
\subsection{Concurrent Actors}
\label{concActor}
A concurrent actor is written slightly differently to a light weight actor; and has a different type and different behavior. Its internals are sufficiently complex that we do not expose them and leave the \q{concurrent actor} type abstract:
\begin{alltt}
concurrent actor has kind type of type;
\end{alltt}
The public type for a \q{concurrent actor} is
\begin{alltt}
concurrent actor of \{ \ldots \}
\end{alltt}
which is aliased to the \q{concActor} type for convenience.
Concurrent actors sequentialize all access to them them -- only one speech action is processed at a given time. If multiple speech actions are attempted simultaneously all but one is blocked while it is processed by the \q{concurrent actor}.
Concurrent actors execute on an independent background \q{task} -- see Section~\vref{backgroundTask}. The normal operational semantics for speech actions still holds with concurrent actors: except that a \q{notify} completes as soon as the concurrent actor starts processing it but before it completes processing the \q{notify}.
Program~\vref{concSieveProg} shows an example using \q{concurrent actor}s. This is a variation of the famous `Sieve of Erastosthenes' method for finding prime numbers.
\begin{program}
\begin{alltt}
filterActor(P) is concurrent actor\{
private var Nx := (_) => task\{\};
\{ Nx := newPrime \};
private fun newPrime(X) is let\{
def Fx is filterActor(X);
fun filterPrime(XX) is task{ notify Fx with XX on input};
\} in task \{
logMsg(info,"new prime $X");
Nx := filterPrime;
\};
on X on input do \{
perform task \{
if X\%P!=0 then
perform Nx(X);
\}
\}
\}
\end{alltt}
\caption{Sieve of Erastosthenes as Concurrent Actors}
\label{concSieveProg}
\end{program}
\begin{aside}
Concurrent actors are more complex internally than simple actors. As such they have a higher internal performance penalty. However, the great merit of concurrent actors is that they can exploit parallelism where it is available.
\end{aside}