577 lines
32 KiB
Markdown
577 lines
32 KiB
Markdown
# Syndicated Actor Model
|
||
|
||
The Syndicated Actor Model (SAM) [[Garnock-Jones 2017][]] is an approach to concurrency based
|
||
on the *Communicating Event-Loop Actor Model* [[De Koster et al 2016][]] as pioneered by E
|
||
[[Miller 2006][]] and AmbientTalk [[Van Cutsem et al 2007][]].
|
||
|
||
While other Actor-like models take message-passing as fundamental, the SAM builds on a
|
||
different underlying primitive: *eventually-consistent replication of state* among actors.
|
||
Message-passing follows as a derived operation.
|
||
|
||
This fundamental difference integrates Tuplespace- [[Gelernter and Carriero 1992][]] and
|
||
publish/subscribe-like ideas with concurrent object-oriented programming, and makes the SAM
|
||
well-suited for building programs and systems that are reactive, robust to change, and graceful
|
||
in the face of partial failure.
|
||
|
||
**Outline.** This document first describes the primitives of SAM interaction, and then briefly
|
||
illustrates their application to distributed state management and handling of partial failure.
|
||
It goes on to present the idea of a *dataspace*, an integration of Tuplespace- and
|
||
publish/subscribe-like ideas with the SAM. Finally, it discusses the SAM's generalization of
|
||
*object capabilities* to allow for control not only over invocation of object behaviour but
|
||
subscription to object state.
|
||
|
||
Throughout, we will limit discussion to interaction among actors connected directly to one
|
||
another: that is, to interaction within a single scope. Scopes can be treated as "subnets" and
|
||
connected together: see the [Syndicate protocol specification](./protocol.md).
|
||
|
||
For more on the SAM, on the concept of "conversational concurrency" that the model is a
|
||
response to, and on other aspects of the larger project that the SAM is a part of, please see
|
||
<https://syndicate-lang.org/about/> and Garnock-Jones' [2017 dissertation][Garnock-Jones 2017].
|
||
|
||
## Concepts and components of SAM interaction
|
||
|
||
A number of inter-related ideas must be taken together to make sense of SAM interaction. This
|
||
section will outline the essentials.
|
||
|
||
For core concepts of Actor models generally, see De Koster *et al.*'s outstanding [2016 survey
|
||
paper][De Koster et al 2016], which lays out a taxonomy of Actor systems as well as introducing
|
||
solid definitions for terms such as "actor", "message", and so on.
|
||
|
||
### Actors, Entities, Assertions and Messages
|
||
|
||
The SAM is based around actors which not only exchange messages, but publish ("assert")
|
||
selected portions of their internal state ("assertions") to their peers in a publish/subscribe,
|
||
reactive manner. Assertions and messages in the SAM are [semi-structured
|
||
data](https://en.wikipedia.org/wiki/Semi-structured_data): their structure allows for
|
||
pattern-matching and [content-based
|
||
routing](https://www.enterpriseintegrationpatterns.com/ContentBasedRouter.html).
|
||
|
||
Assertions are published and withdrawn freely throughout each actor's lifetime. When an actor
|
||
terminates, all its published assertions are automatically withdrawn. This holds for both
|
||
normal and exceptional termination: crashing actors are cleaned up, too.
|
||
|
||
An actor in the SAM comprises
|
||
|
||
- an *inbox*, for receiving events from peers;
|
||
- a *state*, "all the state that is synchronously accessible by that actor" ([De Koster et al 2016][]);
|
||
- a collection of *entities*; and
|
||
- a collection of *outbound assertions*, the data to be automatically retracted upon actor termination.
|
||
|
||
The term "entity" in the SAM denotes a reactive object, owned by a specific
|
||
actor.[^terminology-vs-e] Entities, not actors, are the unit of addressing in the SAM. Every
|
||
published assertion and every sent message is targeted at some entity. Entities never outlive
|
||
their actors—when an actor terminates, its entities become unresponsive—but may have lifetimes
|
||
shorter than their owning actors.
|
||
|
||
Local interactions, among objects (entities) within the state of the same actor, occur
|
||
synchronously. All other interactions are considered "remote", and occur asynchronously.
|
||
|
||
### Turns
|
||
|
||
Each time an event arrives at an actor's inbox, the actor takes a *turn*. [De Koster *et
|
||
al.*][De Koster et al 2016] define turns as follows:
|
||
|
||
> A turn is defined as the processing of a single message by an actor. In other words, a turn
|
||
> defines the process of an actor taking a message from its inbox and processing that message
|
||
> to completion.
|
||
|
||
In the SAM, a turn comprises
|
||
|
||
- the *event* that triggered the turn and the *entity* addressed by the event,
|
||
- the entity's *execution* of its response to the event, and
|
||
- the collection of pending *actions* produced during execution.
|
||
|
||
If a turn proceeds to completion without an exception or other crash, its pending actions are
|
||
delivered to their target entities/actors. If, on the other hand, the turn is aborted for some
|
||
reason, its pending actions are discarded. This transactional "commit" or "rollback" of a turn
|
||
is familiar from other event-loop-style models such as Ken [[Yoo et al 2012][]].
|
||
|
||
### Events and Actions
|
||
|
||
SAM *events* convey a new assertion, retraction of a previously-established assertion, delivery
|
||
of a message, or a request for synchronisation.
|
||
|
||
In response to an event, an actor (entity) schedules *actions* to be performed at the end of
|
||
the turn. Actions include not only publication and retraction of assertions, transmission of
|
||
messages, and issuing of synchronisaton requests, but also termination of the running actor and
|
||
creation of new actors to run alongside the running actor.
|
||
|
||
### Entity References are Object Capabilities
|
||
|
||
As mentioned above, entities are the unit of addressing in the SAM. Assertions and message
|
||
bodies may include *references* to entities. Actors receiving such references may then use them
|
||
as targets for later assertions and messages. Entity references act as [*object
|
||
capabilities*](https://en.wikipedia.org/wiki/Object-capability_model), very similar to those
|
||
offered by E [[Miller 2006][]].
|
||
|
||
Entity references play many roles in SAM interactions, but two are of particular importance.
|
||
First, entity references are used to simulate *functions* and *continuations* for encoding
|
||
remote procedure calls (RPCs). Second, entity references can act like *consumers* or
|
||
*subscribers*, receiving asynchronous notifications about state changes from peers.
|
||
|
||
## Illustrative Examples
|
||
|
||
To show some of the potential of the SAM, we will explore two representative examples: a
|
||
distributed spreadsheet, and a cellular modem server.
|
||
|
||
### Spreadsheet cell
|
||
|
||
Imagine a collection of actors representing portions of a spreadsheet, each containing entities
|
||
representing spreadsheet cells. Each cell entity publishes public aspects of its state to
|
||
interested peers: namely, its current value. It also responds to messages instructing it to
|
||
update its formula. In pseudocode:
|
||
|
||
```pseudocode
|
||
**define entity** Cell(*formula*):
|
||
*subscribers* ← ∅
|
||
**on** assertion from a peer of interest in our value,
|
||
add *peer*, the entity reference carried in the assertion of interest, to *subscribers*
|
||
**on** retraction of previously-expressed interest from some *peer*,
|
||
remove *peer* from *subscribers*
|
||
**assert** subscriptions to other Cells (using entity references in *formula*)
|
||
**on** message conveying a new formula,
|
||
*formula* ← *newFormula*
|
||
**replace** subscription assertions using references in new *formula*
|
||
**on** assertion conveying updated contents relevant to *formula*,
|
||
*value* ← eval(*formula*)
|
||
**continuously**, whenever *value* or *subscribers* changes,
|
||
**assert** the contents of *value* to every peer in *subscribers*,
|
||
**retract**ing previously-asserted values
|
||
```
|
||
|
||
Much of the subscription-management behaviour of Cell is generic: lines 2–6 managing the
|
||
*subscribers* set and lines 13–14 iterating over it will be common to any entity wishing to
|
||
allow observers to track portions of its state. This observation leads to the factoring-out of
|
||
*dataspaces*, introduced below.
|
||
|
||
### Cellular modem server
|
||
|
||
Imagine an actor implementing a simple driver for a cellular modem, that accepts requests (as
|
||
Hayes modem command strings) paired with *continuations* represented as entity references. Any
|
||
responses the modem sends in reply to a command string are delivered to the continuation entity
|
||
as a SAM message.
|
||
|
||
```pseudocode
|
||
**define entity** Server():
|
||
**on** assertion Request(*commandString*, *replyEntity*)
|
||
output *commandString* via modem serial port
|
||
collect response(s) from modem serial port
|
||
**send** response(s) as a message to *replyEntity*
|
||
|
||
**define entity** Client(*serverRef*):
|
||
**define entity** *k*:
|
||
**on** message containing responses,
|
||
**retract** the Request assertion
|
||
(and continue with other tasks)
|
||
**assert** Request(`"AT+CMGS=..."`, *k*) to *serverRef*
|
||
```
|
||
|
||
This is almost a standard continuation-passing style encoding of remote procedure
|
||
call.[^rpc-sam-discussion] However, there is one important difference: the request is sent to
|
||
the remote object not as a message, but as an *assertion*. Assertions, unlike messages, have a
|
||
*lifetime* and so can act to set up a [conversational
|
||
frame](https://syndicate-lang.org/tonyg-dissertation/html/#x_2_2_0_0_1) within which further
|
||
interaction can take place.
|
||
|
||
Here, subsequent interaction appears at first glance to be limited to transmission of a
|
||
response message to *replyEntity*. But what if the Server were to crash before sending a
|
||
response?
|
||
|
||
Erlang [[Armstrong 2003][]] pioneered the use of "links" and "monitors" to detect failure of a
|
||
remote peer during an interaction; "broken promises" and a suite of special system messages
|
||
such as `__whenBroken` and `__reactToLostClient` [[Miller 2006][], chapter 17] do the same for
|
||
E. The SAM instead uses *retraction of previous assertions* to signal failure.
|
||
|
||
To see how this works, we must step away from the pseudocode above and examine the context
|
||
where *serverRef* is discovered for eventual use with Client. In the case that an assertion,
|
||
rather than a message, conveys *serverRef* to the client actor, then when Server *crashes*, the
|
||
assertion conveying *serverRef* is automatically retracted. The client actor, interpreting this
|
||
as failure, can choose to respond appropriately.
|
||
|
||
The ubiquity of these patterns of service discovery and failure signalling also contributed,
|
||
along with the patterns of generic publisher/subscriber state management mentioned above, to
|
||
the factoring-out of dataspaces.
|
||
|
||
## Dataspaces
|
||
|
||
A special kind of syndicated actor entity, a *dataspace*, routes and replicates published data
|
||
according to actors' interests.
|
||
|
||
```pseudocode
|
||
**define entity** Dataspace():
|
||
*allAssertions* ← **new** Bag()
|
||
*allSubscribers* ← **new** Set()
|
||
**on** assertion of semi-structured datum *a*,
|
||
add *a* to *allAssertions*
|
||
if *a* appears exactly once now in *allAssertions*,
|
||
if *a* matches Observe(*pattern*, *subscriberRef*),
|
||
add (*pattern*, *subscriberRef*) to *allSubscribers*
|
||
for *x* in *allAssertions*, if *x* matches *pattern*,
|
||
**assert** *x* at *subscriberRef*
|
||
otherwise,
|
||
for (*p*, *s*) in *allSubscribers*, if *a* matches *p*,
|
||
**assert** *a* at *s*
|
||
**on** retraction of previously-asserted *a*,
|
||
remove *a* from *allAssertions*
|
||
if *a* no longer appears at all in *allAssertions*,
|
||
retract *a* from all subscribers to whom it was forwarded
|
||
if *a* matches Observe(*pattern*, *subscriberRef*),
|
||
remove (*pattern*, *subscriberRef*) from *allSubscribers*
|
||
retract all assertions previously sent to *subscriberRef*
|
||
```
|
||
|
||
Assertions sent to a dataspace are routed by pattern-matching. Subscriptions—tuples associating
|
||
a pattern with a subscriber entity—are placed in the dataspace as assertions like any other.
|
||
|
||
A dataspace entity behaves very similarly to a tuplespace [[Gelernter and Carriero 1992][]].
|
||
However, there are two key differences.
|
||
|
||
The first is that, while tuples in a tuplespace are "generative" [[Gelernter 1985][]], taking
|
||
on independent existence once created and potentially remaining in a tuplespace indefinitely,
|
||
SAM assertions never outlive their asserting actors. This means that assertions placed at a
|
||
dataspace only exist as long as they are actively maintained. If an actor terminates or
|
||
crashes, *all* its assertions are withdrawn, including those targeted at a dataspace entity.
|
||
The dataspace, following its definition, forwards all withdrawals on to interested subscribers.
|
||
|
||
The second is that assertion of a value is idempotent: multiple assertions of the same
|
||
value[^entity-reference-equivalence] appear to observers indistinguishable from a single
|
||
assertion. In other words, assertions at a dataspace are deduplicated.
|
||
|
||
### Applications of dataspaces
|
||
|
||
Dataspaces have many uses. They are ubiquitous in SAM programs. The form of state replication
|
||
embodied in dataspaces subsumes Erlang-style links and monitors, publish/subscribe,
|
||
tuplespaces, presence notifications, directory/naming services, and so on.
|
||
|
||
#### Subscription management
|
||
|
||
The very essence of a dataspace entity is subscription management. Entities wishing to manage
|
||
collections of subscribers can cooperate with dataspaces: they may either manage a private
|
||
dataspace entity, or share a dataspace with other entities. For example, in the spreadsheet
|
||
cell example above, each cell could use its own private dataspace, or all cells could share a
|
||
dataspace by embedding their values in a record alongside some name for the cell.
|
||
|
||
#### Service directory and service discovery
|
||
|
||
Assertions placed at a dataspace may include entity references. This makes a dataspace an ideal
|
||
implementation of a service directory. Services advertise their existence by asserting *service
|
||
presence* [[Konieczny et al 2009][]] records including their names alongside relevant entity
|
||
references:
|
||
|
||
Service(`"name"`, *serviceRef*)
|
||
|
||
Clients discover services by asserting *interest* in such records using patterns:
|
||
|
||
Observe(⌜Service(`"name"`, _)⌝, *clientRef*)
|
||
|
||
Whenever some matching Service record has been asserted by a server, the dataspace asserts the
|
||
corresponding record to *clientRef*. (The real dataspace pattern language includes *binding*,
|
||
not discussed here; see [*"Patterns over
|
||
assertions"*](protocols/syndicate/dataspacePatterns.md) in the Syndicate protocol
|
||
documentation.)
|
||
|
||
#### Failure signalling
|
||
|
||
Since assertions of service presence are withdrawn on failure, and withdrawals are propagated
|
||
to interested subscribers, service clients like *clientRef* above will be automatically
|
||
notified whenever *serviceRef* goes out of service. The same principle can also be applied in
|
||
other similar settings.
|
||
|
||
#### Independence from service identity
|
||
|
||
There's no need to separate service discovery from service interaction. A client may assert its
|
||
request directly at the dataspace; a service may subscribe to requests in the same direct way:
|
||
|
||
`(client:)` ServiceRequest(`"name'`, *arg1*, *arg2*, ..., *replyRef*)
|
||
`(server:)` Observe(⌜ServiceRequest(`"name'`, *?a*, *?b*, ..., *?k*)⌝, *serviceRef*)
|
||
|
||
In fact, there are benefits to doing things this way. If the service should crash
|
||
mid-transaction, then when it restarts, the incomplete ServiceRequest record will remain, and
|
||
it can pick up where it left off. The client has become decoupled from the specific identity of
|
||
the service provider, allowing flexibility that wasn't available before.
|
||
|
||
#### Asserting interest in assertions of interest
|
||
|
||
Subscriptions at a dataspace are assertions like any other. This opens up the possibility of
|
||
reacting to *subscriptions*:
|
||
|
||
Observe(⌜Observe(⌜...⌝, _)⌝, *r*)
|
||
|
||
This allows dataspace subscribers to express interest in *which other subscribers are present*.
|
||
|
||
In many cases, explicit assertion of presence (via, e.g., the Service records above) is the
|
||
right thing to do, but from time to time it can make sense for clients to treat the presence of
|
||
some subscriber interested in their requests as sufficient indication of service presence to go
|
||
ahead.[^background-on-interests]
|
||
|
||
## Illustrative Examples revisited
|
||
|
||
Now that we have Dataspaces in our toolbelt, let's revisit the spreadsheet cell and cellular
|
||
modem examples from above.
|
||
|
||
### Spreadsheet cell with a dataspace
|
||
|
||
```pseudocode
|
||
**define entity** Cell(*dataspaceRef*, *name*, *formula*):
|
||
**continuously**, whenever *value* changes,
|
||
**assert** CellValue(*name*, *value*) to *dataspaceRef*
|
||
**continuously**, whenever *formula* changes,
|
||
for each name *n* in *formula*,
|
||
define entity *k*:
|
||
**on** assertion of *nValue*,
|
||
*value* ← (re)evaluation based on *formula*, *nValue*, and other *nValue*s
|
||
**assert** Observe(⌜CellValue(*n*, *?nValue*)⌝, *k*) to *dataspaceRef*
|
||
**on** message conveying a new formula,
|
||
*formula* ← *newFormula*
|
||
```
|
||
|
||
The cell is able to outsource all subscription management to the *dataspaceRef* it is given.
|
||
Its behaviour function is looking much closer to an abstract prose specification of a
|
||
spreadsheet cell.
|
||
|
||
### Cellular modem server with a dataspace
|
||
|
||
There are many ways to implement RPC using dataspaces,[^rpc-sam-discussion] each with different
|
||
characteristics. This implementation uses anonymous service instances, implicit service names,
|
||
asserted requests, and message-based responses:
|
||
|
||
```pseudocode
|
||
**define entity** Server(*dataspaceRef*):
|
||
**define entity** *serviceRef*:
|
||
**on** assertion of *commandString* and *replyEntity*
|
||
output *commandString* via modem serial port
|
||
collect response(s) from modem serial port
|
||
**send** response(s) as a message to *replyEntity*
|
||
**assert** Observe(⌜Request(*?commandString*, *?replyEntity*)⌝, *serviceRef*) to *dataspaceRef*
|
||
|
||
**define entity** Client(*dataspaceRef*):
|
||
**define entity** *k*:
|
||
**on** message containing responses,
|
||
**retract** the Request assertion
|
||
(and continue with other tasks)
|
||
**assert** Request(`"AT+CMGS=..."`, *k*) to *dataspaceRef*
|
||
```
|
||
|
||
If the service crashes before replying, the client's request remains outstanding, and a service
|
||
supervisor [[Armstrong 2003][], section 4.3.2] can reset the modem and start a fresh service
|
||
instance. The client remains blissfully unaware that anything untoward happened.
|
||
|
||
We may also consider a variation where the client wishes to retract or modify its request in
|
||
case of service crash. To do this, the client must pay more attention to the [conversational
|
||
frame](https://syndicate-lang.org/tonyg-dissertation/html/#x_2_2_0_0_1) of its interaction with
|
||
the server. In the pseudocode above, no explicit service discovery step is used, but the client
|
||
could reason about the server's lifecycle by observing the (disappearance of) presence of the
|
||
server's subscription to requests: Observe(⌜Observe(⌜Request(⌞_⌟, ⌞_⌟)⌝, _)⌝, ...).
|
||
|
||
## Object-capabilities for access control
|
||
|
||
[Object capabilities](https://en.wikipedia.org/wiki/Object-capability_model) are the only
|
||
properly compositional way to secure a distributed system.[^justification-and-examples] They
|
||
are a natural fit for Actor-style systems, as demonstrated by E and its various descendants
|
||
[[Miller 2006][], [Van Cutsem et al 2007][], [Stiegler and Tie 2010][], [Yoo et al 2012][] and
|
||
others], so it makes sense that they would work well for the Syndicated Actor Model.
|
||
|
||
The main difference between SAM capabilities and those in E-style Actor models is that
|
||
syndicated capabilities express pattern-matching-based restrictions on the *assertions* that
|
||
may be directed toward a given entity, as well as the *messages* that may be sent its way.
|
||
|
||
Combined with the fact that subscription is expressed with assertions like any other, this
|
||
yields a mechanism offering control over state replication and observation of replicated state
|
||
as well as ordinary message-passing and RPC.
|
||
|
||
In the SAM, a capability is a triple of
|
||
|
||
- target actor reference,
|
||
- target entity reference within that actor, and
|
||
- an *attenuation* describing accepted assertions and messages.
|
||
|
||
An "attenuation" is a piece of syntax including patterns over semi-structured data. When an
|
||
assertion or message is directed to the underlying entity by way of an attenuated capability,
|
||
the asserted value or message body is checked against the patterns in the attenuation. Values
|
||
not matching are discarded silently.[^silent-discard]
|
||
|
||
**Restricting method calls.** For example, a reference to the dataspace where our cellular
|
||
modem server example is running could be attenuated to only allow assertions of the form
|
||
Request(`"ATA"`, _). This would have the effect of limiting holders of the capability to only
|
||
being able to cause the modem to answer an incoming call ("ATA").
|
||
|
||
**Restricting subscriptions.** As another example, a reference to the dataspace where our
|
||
spreadsheet cells are running could be attenuated to only allow assertions of the form
|
||
Observe(⌜CellValue(`"B13"`, _)⌝, _). This would have the effect of limiting holders of the
|
||
capability to only being able to read the contents (or presence) of cell B13.
|
||
|
||
## Conclusion
|
||
|
||
We have looked at the concepts involved in the Syndicated Actor Model (SAM), an Actor-like
|
||
approach to concurrency that offers a form of concurrent object-oriented programming with
|
||
intrinsic publish/subscribe support. The notion of a *dataspace* factors out common interaction
|
||
patterns and decouples SAM components from one another in useful ways. Object capabilities are
|
||
used in the SAM not only to restrict access to the behaviour offered by objects, but to
|
||
restrict the kinds of subscriptions that can be established to the state published by SAM
|
||
objects.
|
||
|
||
While we have examined some of the high level forms of interaction among entities residing in
|
||
SAM actors, we have not explored techniques for effectively structuring the *internals* of such
|
||
actors. For this, the SAM offers the concept of "facets", which relate directly to
|
||
conversational contexts; for a discussion of these, see Garnock-Jones' [2017
|
||
dissertation][Garnock-Jones 2017], especially [chapter
|
||
2](https://syndicate-lang.org/tonyg-dissertation/html/#x_2_5_0_0_25), [chapter
|
||
5](https://syndicate-lang.org/tonyg-dissertation/html/#CHAP:COMPUTATIONAL-MODEL-II:SYNDICATE),
|
||
[chapter 8](https://syndicate-lang.org/tonyg-dissertation/html/#CHAP:IDIOMATIC-SYNDICATE) and
|
||
[section 11.1](https://syndicate-lang.org/tonyg-dissertation/html/#sec:Placing-PL-on-the-map).
|
||
A less formal [discussion of
|
||
facets](https://syndicate-lang.org/about/#facets-represent-sub-conversations) can also be found
|
||
on the Syndicate project website.
|
||
|
||
## Bibliography
|
||
|
||
[Armstrong 2003]: #ref:armstrong-2003
|
||
[**Armstrong 2003**] <span id="ref:armstrong-2003">Armstrong, Joe. “Making Reliable Distributed
|
||
Systems in the Presence of Software Errors.” PhD, Royal Institute of Technology,
|
||
Stockholm, 2003. [[PDF]](https://erlang.org/download/armstrong_thesis_2003.pdf)</span>
|
||
|
||
[De Koster et al 2016]: #ref:de-koster-2016
|
||
[**De Koster et al 2016**] <span id="ref:de-koster-2016">De Koster, Joeri, Tom Van Cutsem, and
|
||
Wolfgang De Meuter. “43 Years of Actors: A Taxonomy of Actor Models and Their Key Properties.”
|
||
In Proc. AGERE. Amsterdam, The Netherlands, 2016. [[DOI (PDF
|
||
available)]](https://doi.org/10.1145/3001886.3001890)</span>
|
||
|
||
[Felleisen 1991]: #ref:felleisen-1991
|
||
[**Felleisen 1991**] <span id="ref:felleisen-1991">Felleisen, Matthias. “On the Expressive
|
||
Power of Programming Languages.” Science of Computer Programming 17, no. 1–3 (1991): 35–75.
|
||
[[DOI (PDF available)]](https://doi.org/10.1016/0167-6423(91)90036-W)
|
||
[[PS]](https://www2.ccs.neu.edu/racket/pubs/scp91-felleisen.ps.gz)</span>
|
||
|
||
[Fischer et al 1985]: #ref:fischer-1985
|
||
[**Fischer et al 1985**] <span id="ref:fischer-1985">Fischer, Michael J., Nancy A. Lynch, and
|
||
Michael S. Paterson. “Impossibility of Distributed Consensus with One Faulty Process.” Journal
|
||
of the ACM 32, no. 2 (April 1985): 374–382. [[DOI (PDF
|
||
available)]](https://doi.org/10.1145/3149.214121)
|
||
[[PDF]](https://groups.csail.mit.edu/tds/papers/Lynch/jacm85.pdf)</span>
|
||
|
||
[Garnock-Jones 2017]: #ref:garnock-jones-2017
|
||
[**Garnock-Jones 2017**] <span id="ref:garnock-jones-2017">Garnock-Jones, Tony. “Conversational
|
||
Concurrency.” PhD, Northeastern University, 2017.
|
||
[[PDF]](https://syndicate-lang.org/papers/conversational-concurrency-201712310922.pdf)
|
||
[[HTML]](https://syndicate-lang.org/tonyg-dissertation/html)</span>
|
||
|
||
[Gelernter 1985]: #ref:gelernter-1985
|
||
[**Gelernter 1985**] <span id="ref:gelernter-1985">Gelernter, David. “Generative Communication
|
||
in Linda.” ACM TOPLAS 7, no. 1 (January 2, 1985): 80–112.
|
||
[[DOI]](https://doi.org/10.1145/2363.2433)</span>
|
||
|
||
[Gelernter and Carriero 1992]: #ref:gelernter-1992
|
||
[**Gelernter and Carriero 1992**] <span id="ref:gelernter-1992">Gelernter, David, and Nicholas
|
||
Carriero. “Coordination Languages and Their Significance.” Communications of the ACM 35, no. 2
|
||
(February 1, 1992): 97–107. [[DOI]](https://doi.org/10.1145/129630.129635)</span>
|
||
|
||
[Karp 2015]: #ref:karp-2015
|
||
[**Karp 2015**] <span id="ref:karp-2015">Karp, Alan H. “Access Control for IoT: A Position
|
||
Paper.” In IEEE Workshop on Security and Privacy for IoT. Washington, DC, USA, 2015.
|
||
[[PDF]](https://alanhkarp.com/publications/Access-Control-for-IoT.pdf)</span>
|
||
|
||
[Konieczny et al 2009]: #ref:konieczny-2009
|
||
[**Konieczny et al 2009**] <span id="ref:konieczny-2009">Konieczny, Eric, Ryan Ashcraft, David
|
||
Cunningham, and Sandeep Maripuri. “Establishing Presence within the Service-Oriented
|
||
Environment.” In IEEE Aerospace Conference. Big Sky, Montana, 2009.
|
||
[[DOI]](https://doi.org/10.1109/AERO.2009.4839647)</span>
|
||
|
||
[Miller 2006]: #ref:miller-2006
|
||
[**Miller 2006**] <span id="ref:miller-2006">Miller, Mark S. “Robust Composition: Towards a
|
||
Unified Approach to Access Control and Concurrency Control.” PhD, Johns Hopkins
|
||
University, 2006. [[PDF]](http://www.erights.org/talks/thesis/markm-thesis.pdf)</span>
|
||
|
||
[Morris 1968]: #ref:morris-1968
|
||
[**Morris 1968**] <span id="ref:morris-1968">Morris, James Hiram, Jr. “Lambda-Calculus Models
|
||
of Programming Languages.” PhD thesis, Massachusetts Institute of Technology, 1968. [[Available
|
||
online]](http://hdl.handle.net/1721.1/64850)</span>
|
||
|
||
[Stiegler and Tie 2010]: #ref:stiegler-2010
|
||
[**Stiegler and Tie 2010**] <span id="ref:stiegler-2010">Stiegler, Marc, and Jing Tie.
|
||
“Introduction to Waterken Programming.” Technical Report. Hewlett-Packard Labs, August 6, 2010.
|
||
[[Available online]](https://www.hpl.hp.com/techreports/2010/HPL-2010-89.html)</span>
|
||
|
||
[Van Cutsem et al 2007]: #ref:van-cutsem-2007
|
||
[**Van Cutsem et al 2007**] <span id="ref:van-cutsem-2007">Van Cutsem, Tom, Stijn Mostinckx,
|
||
Elisa González Boix, Jessie Dedecker, and Wolfgang De Meuter. “AmbientTalk: Object-Oriented
|
||
Event-Driven Programming in Mobile Ad Hoc Networks.” In Proc. XXVI Int. Conf. of the Chilean
|
||
Soc. of Comp. Sci. (SCCC’07). Iquique, Chile, 2007.
|
||
[[DOI]](https://doi.org/10.1109/SCCC.2007.12)
|
||
|
||
[Yoo et al 2012]: #ref:yoo-2012
|
||
[**Yoo et al 2012**] <span id="ref:yoo-2012">Yoo, Sunghwan, Charles Killian, Terence Kelly,
|
||
Hyoun Kyu Cho, and Steven Plite. “Composable Reliability for Asynchronous Systems.” In Proc.
|
||
USENIX Annual Technical Conference. Boston, Massachusetts, 2012.
|
||
[[Talk]](https://www.usenix.org/conference/atc12/technical-sessions/presentation/yoo)
|
||
[[PDF]](https://www.usenix.org/system/files/conference/atc12/atc12-final206-7-20-12.pdf)
|
||
[[Project page]](https://web.eecs.umich.edu/~tpkelly/Ken/)</span>
|
||
|
||
|
||
----
|
||
|
||
#### Notes
|
||
|
||
<!--
|
||
[^message-passing-derived]: A minimal theoretical Syndicated Actor Model includes *only*
|
||
assertion publication and retraction. Message transmission is excluded because,
|
||
theoretically, it can be *defined* as a "brief" assertion of the message body; that is, as
|
||
an assertion, followed "almost immediately" by a matching retraction. This naturally
|
||
captures a number of interesting properties of messages, including potential message loss
|
||
and corruption as well as issues related to medium access control. While it is useful
|
||
theoretically to view message exchange as a pattern (in the "software design pattern"
|
||
sense) of assertion usage, the pattern is so common in practical programming that the SAM
|
||
and its implementations include integrated support for messages as
|
||
standard.[^analogy-with-function-call]
|
||
|
||
[^analogy-with-function-call]: Consider the analogy to a similarly-fundamental design pattern:
|
||
function call. It can be usefully expressed in simpler terms, which expose interesting
|
||
aspects of and variations upon the pattern, but its utility makes it ubiquitous enough to
|
||
deserve special support not only from most programming languages, but from most *hardware*.
|
||
-->
|
||
|
||
[^terminology-vs-e]: The terminology used in the SAM connects to the names used in E [[Miller
|
||
2006][]] as follows: our *actors* are E's *vats*; our *entities* are E's *objects*.
|
||
|
||
[^rpc-sam-discussion]: Many variations on RPC are discussed in section 8.7 of Garnock-Jones'
|
||
[2017 dissertation][Garnock-Jones 2017] ([direct link to relevant section of online
|
||
text](https://syndicate-lang.org/tonyg-dissertation/html/#sec:RPC)).
|
||
|
||
[^entity-reference-equivalence]: Here the thorny question of the equivalence of entity
|
||
references rears its head. Preserves specifies an equivalence over its `Value`s that is
|
||
generic in the equivalence over embedded values such as entity references. The ideal
|
||
equivalence here would be *observational equivalence* [[Morris 1968][], [Felleisen
|
||
1991][]]: two references are the same when they react indistinguishably to assertions and
|
||
messages. However, this isn't something that can be practically implemented except in
|
||
relatively limited circumstances. Fortunately, in most cases, *pointer equivalence* of
|
||
entity references is good enough to work with, and that's what I've implemented to date
|
||
(modulo details such as structural comparison of attenuations attached to a reference
|
||
etc.).
|
||
|
||
[^background-on-interests]: For more on assertions of interest, see
|
||
[here](https://syndicate-lang.org/about/#conversational-frames-conversational-knowledge) and
|
||
[here](https://syndicate-lang.org/tonyg-dissertation/html/#x_2_2_0_0_8).
|
||
|
||
[^justification-and-examples]: Karp [[2015][Karp 2015]] offers a good justification of this
|
||
claim along with a worked example of object-capabilities in a personal-computing setting.
|
||
The capabilities are ordinary E-style capabilities rather than SAM-style capabilities, but
|
||
the conclusions hold.
|
||
|
||
[^silent-discard]: You might be wondering "why *silent* discard of assertions rejected by an
|
||
attenuation filter?", or more generally, "why discard assertions and messages silently on
|
||
any kind of failure?" The answer is related to the famous *Fischer/Lynch/Paterson (FLP)
|
||
result* [[Fischer et al 1985][]], where one cannot distinguish between a failed process or
|
||
a slow process. By extending the reasoning to a process that simply ignores some or all of
|
||
its inputs, we see that offering any kind of response *at the SAM level* in case of failure
|
||
or rejection would be a false comfort, because nothing would prevent successful delivery of
|
||
a message to a recipient which then simply discards it. Instead, processes have to agree
|
||
ahead of time on the [conversational
|
||
frame](https://syndicate-lang.org/tonyg-dissertation/html/#x_2_2_0_0_1) in which they will
|
||
communicate. The SAM encourages a programming style where assertions are used to set up a
|
||
conversational frame, and then other interactions happen in the context of the information
|
||
carried in those assertions; see the section where we [revisit the cellular modem
|
||
server](#cellular-modem-server-with-a-dataspace) with the components decoupled and placed
|
||
in a conversational frame by addition of a dataspace to the system. Finally, and with all
|
||
this said, *debugging-level* notifications of rejected or discarded messages have their
|
||
place: it's just the SAM itself that does not include feedback of this kind. Implementions
|
||
are encouraged to offer such aids to debugging.
|