This paper was converted on www.awesomepapers.org from LaTeX by an anonymous user.
Want to know more? Visit the Converter page.

University of Illinois at Urbana-Champaign, [email protected] of Illinois at Urbana-Champaign, [email protected] \CopyrightDan Plyukhin and Gul Agha {CCSXML} <ccs2012> <concept> <concept_id>10010147.10011777.10011778</concept_id> <concept_desc>Computing methodologies Concurrent algorithms</concept_desc> <concept_significance>500</concept_significance> </concept> <concept> <concept_id>10011007.10010940.10010941.10010949.10010950.10010954</concept_id> <concept_desc>Software and its engineering Garbage collection</concept_desc> <concept_significance>500</concept_significance> </concept> </ccs2012> \ccsdesc[500]Computing methodologies Concurrent algorithms \ccsdesc[500]Software and its engineering Garbage collection \supplement\fundingThis work was supported in part by the National Science Foundation under Grant No. SHF 1617401, and in part by the Laboratory Directed Research and Development program at Sandia National Laboratories, a multi-mission laboratory managed and operated by National Technology and Engineering Solutions of Sandia, LLC, a wholly owned subsidiary of Honeywell International, Inc., for the U.S. Department of Energy’s National Nuclear Security Administration under contract DE-NA0003525.

Acknowledgements.
We would like to thank Dipayan Mukherjee, Atul Sandur, Charles Kuch, Jerry Wu, and the anonymous referees for providing valuable feedback in earlier versions of this work. \EventEditorsIgor Konnov and Laura Kovács \EventNoEds2 \EventLongTitle31st International Conference on Concurrency Theory (CONCUR 2020) \EventShortTitleCONCUR 2020 \EventAcronymCONCUR \EventYear2020 \EventDateSeptember 1–4, 2020 \EventLocationVienna, Austria \EventLogo \SeriesVolume2017 \ArticleNo44

Scalable Termination Detection for Distributed Actor Systems

Dan Plyukhin    Gul Agha
Abstract

Automatic garbage collection (GC) prevents certain kinds of bugs and reduces programming overhead. GC techniques for sequential programs are based on reachability analysis. However, testing reachability from a root set is inadequate for determining whether an actor is garbage because an unreachable actor may send a message to a reachable actor. Instead, it is sufficient to check termination (sometimes also called quiescence): an actor is terminated if it is not currently processing a message and cannot receive a message in the future. Moreover, many actor frameworks provide all actors with access to file I/O or external storage; without inspecting an actor’s internal code, it is necessary to check that the actor has terminated to ensure that it may be garbage collected in these frameworks. Previous algorithms to detect actor garbage require coordination mechanisms such as causal message delivery or nonlocal monitoring of actors for mutation. Such coordination mechanisms adversely affect concurrency and are therefore expensive in distributed systems. We present a low-overhead reference listing technique (called DRL) for termination detection in actor systems. DRL is based on asynchronous local snapshots and message-passing between actors. This enables a decentralized implementation and transient network partition tolerance. The paper provides a formal description of DRL, shows that all actors identified as garbage have indeed terminated (safety), and that all terminated actors–under certain reasonable assumptions–will eventually be identified (liveness).

keywords:
actors, concurrency, termination detection, quiescence detection, garbage collection, distributed systems
category:
\relatedversion

1 Introduction

The actor model [1, 2] is a foundational model of concurrency that has been widely adopted for its scalability: for example, actor languages have been used to implement services at PayPal [19], Discord [27], and in the United Kingdom’s National Health Service database [18]. In the actor model, stateful processes known as actors execute concurrently and communicate by sending asynchronous messages to other actors, provided they have a reference (also called a mail address or address in the literature) to the recipient. Actors can also spawn new actors. An actor is said to be garbage if it can be destroyed without affecting the system’s observable behavior.

Although a number of algorithms for automatic actor GC have been proposed [10, 13, 24, 25, 28, 30], actor languages and frameworks currently popular in industry (such as Akka [4], Erlang [5], and Orleans [8]) require that programmers garbage collect actors manually. We believe this is because the algorithms proposed thus far are too expensive to implement in distributed systems. In order to find applicability in real-world actor runtimes, we argue that a GC algorithm should satisfy the following properties:

  1. 1.

    (Low latency) GC should not restrict concurrency in the application.

  2. 2.

    (High throughput) GC should not impose significant space or message overhead.

  3. 3.

    (Scalability) GC should scale with the number of actors and nodes in the system.

To the best of our knowledge, no previous algorithm satisfies all three constraints. The first requirement precludes any global synchronization between actors, a “stop-the-world” step, or a requirement for causal order delivery of all messages. The second requirement means that the number of additional “control” messages imposed by the algorithm should be minimal. The third requirement precludes algorithms based on global snapshots, since taking a global snapshot of a system with a large number of nodes is infeasible.

To address these goals, we have developed a garbage collection technique called DRL for Deferred Reference Listing. The primary advantage of DRL is that it is decentralized and incremental: local garbage can be collected at one node without communicating with other nodes. Garbage collection can be performed concurrently with the application and imposes no message ordering constraints. We also expect DRL to be reasonably efficient in practice, since it does not require many additional messages or significant actor-local computation.

DRL works as follows. The communication protocol (Section 4) tracks information, such as references and message counts, and stores it in each actor’s state. Actors periodically send out copies of their local state (called snapshots) to be stored at one or more designated snapshot aggregator actors. Each aggregator periodically searches its local store to find a subset of snapshots representing terminated actors (Section 6). Once an actor is determined to have terminated, it can be garbage collected by, for example, sending it a self-destruct message. Note that our termination detection algorithm itself is location transparent.

Since DRL is defined on top of the actor model, it is oblivious to details of a particular implementation (such as how sequential computations are represented). Our technique is therefore applicable to any actor framework and can be implemented as a library. Moreover, it can also be applied to open systems, allowing a garbage-collected actor subsystem to interoperate with an external actor system.

The outline of the paper is as follows. We provide a characterization of actor garbage in Section 2 and discuss related work in Section 3. We then provide a specification of the DRL protocol in Section 4. In Section 5, we describe a key property of DRL called the Chain Lemma. This lemma allows us to prove the safety and liveness properties, which are stated in Section 6. We then conclude in Section 7 with some discussion of future work and how DRL may be used in practice. To conserve space, all proofs have been relegated to the Appendix.

2 Preliminaries

An actor can only receive a message when it is idle. Upon receiving a message, it becomes busy. A busy actor can perform an unbounded sequence of actions before becoming idle. In [3], an action may be to spawn an actor, send a message, or perform a (local) computation. We will also assume that actors can perform effects, such as file I/O. The actions an actor performs in response to a message are dictated by its application-level code, called a behavior.

Actors can also receive messages from external actors (such as the user) by becoming receptionists. An actor AA becomes a receptionist when its address is exposed to an external actor. Subsequently, any external actor can potentially obtain AA’s address and send it a message. It is not possible for an actor system to determine when all external actors have “forgotten” a receptionist’s address. We will therefore assume that an actor can never cease to be a receptionist once its address has been exposed.

mmBBAACCFFDDEEAABusyReferenceMessagemmAAIdleBBAACCFFDDEE(1)(2)AATerminated
Figure 1: A simple actor system. The first configuration leads to the second after CC receives the message mm, which contains a reference to EE. Notice that an actor can send a message and “forget” its reference to the recipient before the message is delivered, as is the case for actor FF. In both configurations, EE is a potential acquaintance of CC, and DD is potentially reachable from CC. The only terminated actor is FF because all other actors are potentially reachable from unblocked actors.

An actor is said to be garbage if it can be destroyed without affecting the system’s observable behavior. However, without analyzing an actor’s code, it is not possible to know whether it will have an effect when it receives a message. We will therefore restrict our attention to actors that can be guaranteed to be garbage without inspecting their behavior. According to this more conservative definition, any actor that might receive a message in the future should not be garbage collected because it could, for instance, write to a log file when it becomes busy. Conversely, any actor that is guaranteed to remain idle indefinitely can safely be garbage collected because it will never have any effects; such an actor is said to be terminated. Hence, garbage actors coincide with terminated actors in our model.

Terminated actors can be detected by looking at the global state of the system. We say that an actor BB is a potential acquaintance of AA (and AA is a potential inverse acquaintance of BB) if AA has a reference to BB or if there is an undelivered message to AA that contains a reference to BB. We define potential reachability to be the reflexive transitive closure of the potential acquaintance relation. If an actor is idle and has no undelivered messages, then it is blocked; otherwise it is unblocked. We then observe that an actor is terminated when it is only potentially reachable by blocked actors: Such an actor is idle, blocked, and can only potentially be sent a message by other idle blocked actors. Conversely, without analyzing actor code we cannot safely conclude that an actor is terminated if it is potentially reachable by an unblocked actor. Hence, we say that an actor is terminated if and only if it is blocked and all of its potential inverse acquaintances are terminated.

3 Related Work

Global Termination

Global termination detection (GTD) is used to determine when all processes have terminated [17, 16]. For GTD, it suffices to obtain global message send and receive counts. Most GTD algorithms also assume a fixed process topology. However, Lai gives an algorithm in [14] that supports dynamic topologies such as in the actor model. Lai’s algorithm performs termination detection in “waves”, disseminating control messages along a spanning tree (such as an actor supervisor hierarchy) so as to obtain consistent global message send and receive counts. Venkatasubramanian et al. take a similar approach to obtain a consistent global snapshot of actor states in a distributed system [25]. However, such an approach does not scale well because it is not incremental: garbage cannot be detected until all nodes in the system have responded. In contrast, DRL does not require a global snapshot, does not require actors to coordinate their local snapshots, and does not require waiting for all nodes before detecting local terminated actors.

Reference Tracking

We say that an idle actor is simple garbage if it has no undelivered messages and no other actor has a reference to it. Such actors can be detected with distributed reference counting [31, 6, 20] or with reference listing [21, 30] techniques. In reference listing algorithms, each actor maintains a partial list of actors that may have references to it. Whenever AA sends BB a reference to CC, it also sends an 𝚒𝚗𝚏𝚘\mathtt{info} message informing CC about BB’s reference. Once BB no longer needs a reference to CC, it informs CC by sending a 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release} message; this message should not be processed by CC until all preceding messages from BB to CC have been delivered. Thus an actor is simple garbage when its reference listing is empty.

Our technique uses a form of deferred reference listing, in which AA may also defer sending 𝚒𝚗𝚏𝚘\mathtt{info} messages to CC until it releases its references to CC. This allows 𝚒𝚗𝚏𝚘\mathtt{info} and 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release} messages to be batched together, reducing communication overhead.

Cyclic Garbage

Actors that are transitively acquainted with one another are said to form cycles. Cycles of terminated actors are called cyclic garbage and cannot be detected with reference listing alone. Since actors are hosted on nodes and cycles may span across multiple nodes, detecting cyclic garbage requires sharing information between nodes to obtain a consistent view of the global topology. One approach is to compute a global snapshot of the distributed system [13] using the Chandy-Lamport algorithm [9]; but this requires pausing execution of all actors on a node to compute its local snapshot.

Another approach is to add edges to the actor reference graph so that actor garbage coincides with passive object garbage [24, 29]. This is convenient because it allows existing algorithms for distributed passive object GC, such as [23], to be reused in actor systems. However, such transformations require that actors know when they have undelivered messages, which requires some form of synchronization.

To avoid pausing executions, Wang and Varela proposed a reference listing based technique called the pseudo-root algorithm. The algorithm computes approximate global snapshots and is implemented in the SALSA runtime [30, 28]. The pseudo-root algorithm requires a high number of additional control messages and requires actors to write to shared memory if they migrate or release references during snapshot collection. Our protocol requires fewer control messages and no additional actions between local actor snapshots. Wang and Varela also explicitly address migration of actors, a concern orthogonal to our algorithm.

Our technique is inspired by MAC, a termination detection algorithm implemented in the Pony runtime [10]. In MAC, actors send a local snapshot to a designated cycle detector whenever their message queue becomes empty, and send another notification whenever it becomes non-empty. Clebsch and Drossopoulou prove that for systems with causal message delivery, a simple request-reply protocol is sufficient to confirm that the cycle detector’s view of the topology is consistent. However, enforcing causal delivery in a distributed system imposes additional space and networking costs [11, 7]. DRL is similar to MAC, but does not require causal message delivery, supports decentralized termination detection, and actors need not take snapshots each time their message queues become empty. The key insight is that these limitations can be removed by tracking additional information at the actor level.

An earlier version of DRL appeared in [22]. In this paper, we formalize the description of the algorithm and prove its safety and liveness. In the process, we discovered that release acknowledgment messages are unnecessary and that termination detection is more flexible than we first thought: it is not necessary for GC to be performed in distinct “phases” where every actor takes a snapshot in each phase. In particular, once an idle actor takes a snapshot, it need not take another snapshot until it receives a fresh message.

4 A Two-Level Semantic Model

Our computation model is based on the two level approach to actor semantics [26], in which a lower system-level transition system interprets the operations performed by a higher, user-facing application-level transition system. In this section, we define the DRL communication protocol at the system level. We do not provide a transition system for the application level computation model, since it is not relevant to garbage collection (see [3] for how it can be done). What is relevant to us is that corresponding to each application-level action is a system-level transition that tracks references. We will therefore define system-level configurations and transitions on system-level configurations. We will refer to these, respectively, as configurations and transitions in the rest of the paper.

4.1 Overview

Actors in DRL use reference objects (abbreviated refobs) to send messages, instead of using plain actor addresses. Refobs are similar to unidirectional channels and can only be used by their designated owner to send messages to their target; thus in order for AA to give BB a reference to CC, it must explicitly create a new refob owned by BB. Once a refob is no longer needed, it should be deactivated by its owner and removed from local state.

The DRL communication protocol enriches each actor’s state with a list of refobs that it currently owns and associated message counts representing the number of messages sent using each refob. Each actor also maintains a subset of the refobs of which it is the target, together with associated message receive counts. Lastly, actors perform a form of “contact tracing” by maintaining a subset of the refobs that they have created for other actors; we provide details about the bookkeeping later in this section.

The additional information above allows us to detect termination by inspecting actor snapshots. If a set of snapshots is consistent (in the sense of [9]) then we can use the “contact tracing” information to determine whether the set is closed under the potential inverse acquaintance relation (see Section 5). Then, given a consistent and closed set of snapshots, we can use the message counts to determine whether an actor is blocked. We can therefore find all the terminated actors within a consistent set of snapshots.

In fact, DRL satisfies a stronger property: any set of snapshots that “appears terminated” in the sense above is guaranteed to be consistent. Hence, given an arbitrary closed set of snapshots, it is possible to determine which of the corresponding actors have terminated. This allows a great deal of freedom in how snapshots are aggregated. For instance, actors could place their snapshots in a global eventually consistent store, with a garbage collection thread at each node periodically inspecting the store for local terminated actors.

Reference Objects

mmBBAACCFFDDEEAABusyReferenceMessagemmAAIdleBBAACCFFDDEE(1)(2)AATerminatedCCAAyyCCAABBxxyyCCAABBxxyy𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(y,z)\mathtt{CreatedUsing}(y,z)𝚊𝚙𝚙(x,{z})\mathtt{app}(x,\{z\})CCAABBxxyy𝙰𝚌𝚝𝚒𝚟𝚎(z)\mathtt{Active}(z)𝚒𝚗𝚏𝚘(y,z)\mathtt{info}(y,z)CCAABBxxyy𝙲𝚛𝚎𝚊𝚝𝚎𝚍(z)\mathtt{Created}(z)𝚛𝚎𝚕𝚎𝚊𝚜𝚎(z)\mathtt{release}(z)CCAABBxxyy𝙲𝚛𝚎𝚊𝚝𝚎𝚍(z)\mathtt{Created}(z)𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(z)\mathtt{Released}(z)AAxxmm(2)(4)(6)(1)(3)(5)zzAABusy ActorReferenceMessageIdle Actor
Figure 2: An example showing how refobs are created and destroyed. Below each actor we list all the “facts” related to zz that are stored in its local state. Although not pictured in the figure, AA also obtains facts 𝙰𝚌𝚝𝚒𝚟𝚎(x)\mathtt{Active}(x) and 𝙰𝚌𝚝𝚒𝚟𝚎(y)\mathtt{Active}(y) after spawning actors BB and CC, respectively. Likewise, actors B,CB,C obtain facts 𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x),𝙲𝚛𝚎𝚊𝚝𝚎𝚍(y)\mathtt{Created}(x),\mathtt{Created}(y), respectively, upon being spawned.

A refob is a triple (x,A,B)(x,A,B), where AA is the owner actor’s address, BB is the target actor’s address, and xx is a globally unique token. An actor can cheaply generate such a token by combining its address with a local sequence number, since actor systems already guarantee that each address is unique. We will stylize a triple (x,A,B)(x,A,B) as x:AB{x:A\multimap B}. We will also sometimes refer to such a refob as simply xx, since tokens act as unique identifiers.

When an actor AA spawns an actor BB (Fig. 2 (1, 2)) the DRL protocol creates a new refob x:AB{x:A\multimap B} that is stored in both AA and BB’s system-level state, and a refob y:BB{y:B\multimap B} in BB’s state. The refob xx allows AA to send application-level messages to BB. These messages are denoted 𝚊𝚙𝚙(x,R)\mathtt{app}(x,R), where RR is the sett of refobs contained in the message that AA has created for BB. The refob yy corresponds to the self variable present in some actor languages.

If AA has active refobs x:AB{x:A\multimap B} and y:AC{y:A\multimap C}, then it can create a new refob z:BC{z:B\multimap C} by generating a token zz. In addition to being sent to BB, this refob must also temporarily be stored in AA’s system-level state and marked as “created using yy” (Fig. 2 (3)). Once BB receives zz, it must add the refob to its system-level state and mark it as “active” (Fig. 2 (4)). Note that BB can have multiple distinct refobs that reference the same actor in its state; this can be the result of, for example, several actors concurrently sending refobs to BB. Transition rules for spawning actors and sending messages are given in Section 4.3.

Actor AA may remove zz from its state once it has sent a (system-level) 𝚒𝚗𝚏𝚘\mathtt{info} message informing CC about zz (Fig. 2 (4)). Similarly, when BB no longer needs its refob for CC, it can “deactivate” zz by removing it from local state and sending CC a (system-level) 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release} message (Fig. 2 (5)). Note that if BB already has a refob z:BC{z:B\multimap C} and then receives another z:BC{z^{\prime}:B\multimap C}, then it can be more efficient to defer deactivating the extraneous zz^{\prime} until zz is also no longer needed; this way, the 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release} messages can be batched together.

When CC receives an 𝚒𝚗𝚏𝚘\mathtt{info} message, it records that the refob has been created, and when CC receives a 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release} message, it records that the refob has been released (Fig. 2 (6)). Note that these messages may arrive in any order. Once CC has received both, it is permitted to remove all facts about the refob from its local state. Transition rules for these reference listing actions are given in Section 4.4.

Once a refob has been created, it cycles through four states: pending, active, inactive, or released. A refob z:BC{z:B\multimap C} is said to be pending until it is received by its owner BB. Once received, the refob is active until it is deactivated by its owner, at which point it becomes inactive. Finally, once CC learns that zz has been deactivated, the refob is said to be released. A refob that has not yet been released is unreleased.

Slightly amending the definition we gave in Section 2, we say that BB is a potential acquaintance of AA (and AA is a potential inverse acquaintance of BB) when there exists an unreleased refob x:AB{x:A\multimap B}. Thus, BB becomes a potential acquaintance of AA as soon as xx is created, and only ceases to be an acquaintance once it has received a 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release} message for every refob y:AB{y:A\multimap B} that has been created so far.

mmBBAACCFFDDEEAABusyReferenceMessagemmAAIdleBBAACCFFDDEE(1)(2)AATerminatedCCAAyyCCAABBxxyyCCAABBxxyy𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(y,z)\mathtt{CreatedUsing}(y,z)𝚊𝚙𝚙(x,{z})\mathtt{app}(x,\{z\})CCAABBxxyy𝙰𝚌𝚝𝚒𝚟𝚎(z)\mathtt{Active}(z)𝚒𝚗𝚏𝚘(y,z)\mathtt{info}(y,z)CCAABBxxyy𝙲𝚛𝚎𝚊𝚝𝚎𝚍(z)\mathtt{Created}(z)𝚛𝚎𝚕𝚎𝚊𝚜𝚎(z)\mathtt{release}(z)CCAABBxxyy𝙲𝚛𝚎𝚊𝚝𝚎𝚍(z)\mathtt{Created}(z)𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(z)\mathtt{Released}(z)AAxxmm(2)(4)(6)(1)(3)(5)zzAABusy ActorReferenceMessageIdle ActorAABBCCt1t_{1}t0t_{0}𝚊𝚙𝚙(x)\mathtt{app}(x)𝚊𝚙𝚙(y)\mathtt{app}(y)𝚛𝚎𝚕𝚎𝚊𝚜𝚎(y)\mathtt{release}(y)𝚊𝚙𝚙(y)\mathtt{app}(y^{\prime})t2t_{2}t3t_{3}𝚊𝚙𝚙(x)\mathtt{app}(x)𝚊𝚙𝚙(x,{y})\mathtt{app}(x,\{y^{\prime}\})𝚂𝚎𝚗𝚝(y,1)\mathtt{Sent}(y,1)𝚂𝚎𝚗𝚝(y,2)\mathtt{Sent}(y,2)𝚂𝚎𝚗𝚝(y,1)\mathtt{Sent}(y^{\prime},1)\emptyset𝚁𝚎𝚌𝚟(y,1)\mathtt{Recv}(y,1)𝚁𝚎𝚌𝚟(y,2)\mathtt{Recv}(y,2)𝚁𝚎𝚌𝚟(y,1)\mathtt{Recv}(y^{\prime},1)\emptyset
Figure 3: A time diagram for actors A,B,CA,B,C, demonstrating message counts and consistent snapshots. Dashed arrows represent messages and dotted lines represent consistent cuts. In each cut above, BB’s message send count agrees with CC’s message receive count.

Message Counts and Snapshots

For each refob x:AB{x:A\multimap B}, the owner AA counts the number of 𝚊𝚙𝚙\mathtt{app} and 𝚒𝚗𝚏𝚘\mathtt{info} messages sent along xx; this count can be deleted when AA deactivates xx. Each message is annotated with the refob used to send it. Whenever BB receives an 𝚊𝚙𝚙\mathtt{app} or 𝚒𝚗𝚏𝚘\mathtt{info} message along xx, it correspondingly increments a receive count for xx; this count can be deleted once xx has been released. Thus the memory overhead of message counts is linear in the number of unreleased refobs.

A snapshot is a copy of all the facts in an actor’s system-level state at some point in time. We will assume throughout the paper that in every set of snapshots QQ, each snapshot was taken by a different actor. Such a set is also said to form a cut. Recall that a cut is consistent if no snapshot in the cut causally precedes any other [9]. Let us also say that QQ is a set of mutually quiescent snapshots if there are no undelivered messages between actors in the cut. That is, if AQA\in Q sent a message to BQB\in Q before taking a snapshot, then the message must have been delivered before BB took its snapshot. Notice that if all snapshots in QQ are mutually quiescent, then QQ is consistent.

Notice also that in Fig. 3, the snapshots of BB and CC are mutually quiescent when their send and receive counts agree. This is ensured in part because each refob has a unique token: If actors associated message counts with actor names instead of tokens, then BB’s snapshots at t0t_{0} and t3t_{3} would both contain 𝚂𝚎𝚗𝚝(C,1)\mathtt{Sent}(C,1). Thus, BB’s snapshot at t3t_{3} and CC’s snapshot at t0t_{0} would appear mutually quiescent, despite having undelivered messages in the cut.

We would like to conclude that snapshots from two actors A,BA,B are mutually quiescent if and only if their send and receive counts are agreed for every refob x:AB{x:A\multimap B} or y:BA{y:B\multimap A}. Unfortunately, this fails to hold in general for systems with unordered message delivery. It also fails to hold when, for instance, the owner actor takes a snapshot before the refob is activated and the target actor takes a snapshot after the refob is released. In such a case, neither knowledge set includes a message count for the refob and they therefore appear to agree. However, we show that the message counts can nevertheless be used to bound the number of undelivered messages for purposes of our algorithm (Lemma A.5).

Definitions

We use the capital letters A,B,C,D,EA,B,C,D,E to denote actor addresses. Tokens are denoted x,y,zx,y,z, with a special reserved token 𝚗𝚞𝚕𝚕\mathtt{null} for messages from external actors.

A fact is a value that takes one of the following forms: 𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x)\mathtt{Created}(x), 𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x)\mathtt{Released}(x), 𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(x,y)\mathtt{CreatedUsing}(x,y), 𝙰𝚌𝚝𝚒𝚟𝚎(x)\mathtt{Active}(x), 𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x)\mathtt{Unreleased}(x), 𝚂𝚎𝚗𝚝(x,n)\mathtt{Sent}(x,n), or 𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍(x,n)\mathtt{Received}(x,n) for some refobs x,yx,y and natural number nn. Each actor’s state holds a set of facts about refobs and message counts called its knowledge set. We use ϕ,ψ\phi,\psi to denote facts and Φ,Ψ\Phi,\Psi to denote finite sets of facts. Each fact may be interpreted as a predicate that indicates the occurrence of some past event. Interpreting a set of facts Φ\Phi as a set of axioms, we write Φϕ\Phi\vdash\phi when ϕ\phi is derivable by first-order logic from Φ\Phi with the following additional rules:

  • If (n,𝚂𝚎𝚗𝚝(x,n)Φ)(\not\exists n\in\mathbb{N},\ \mathtt{Sent}(x,n)\in\Phi) then Φ𝚂𝚎𝚗𝚝(x,0)\Phi\vdash\mathtt{Sent}(x,0)

  • If (n,𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍(x,n)Φ)(\not\exists n\in\mathbb{N},\ \mathtt{Received}(x,n)\in\Phi) then Φ𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍(x,0)\Phi\vdash\mathtt{Received}(x,0)

  • If Φ𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x)¬𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x)\Phi\vdash\mathtt{Created}(x)\land\lnot\mathtt{Released}(x) then Φ𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x)\Phi\vdash\mathtt{Unreleased}(x)

  • If Φ𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(x,y)\Phi\vdash\mathtt{CreatedUsing}(x,y) then Φ𝙲𝚛𝚎𝚊𝚝𝚎𝚍(y)\Phi\vdash\mathtt{Created}(y)

For convenience, we define a pair of functions incSent(x,Φ),incRecv(x,Φ)\emph{incSent}(x,\Phi),\emph{incRecv}(x,\Phi) for incrementing message send/receive counts, as follows: If 𝚂𝚎𝚗𝚝(x,n)Φ\mathtt{Sent}(x,n)\in\Phi for some nn, then incSent(x,Φ)=(Φ{𝚂𝚎𝚗𝚝(x,n)}){𝚂𝚎𝚗𝚝(x,n+1)}\emph{incSent}(x,\Phi)=(\Phi\setminus\{\mathtt{Sent}(x,n)\})\cup\{\mathtt{Sent}(x,n+1)\}; otherwise, incSent(x,Φ)=Φ{𝚂𝚎𝚗𝚝(x,1)}\emph{incSent}(x,\Phi)=\Phi\cup\{\mathtt{Sent}(x,1)\}. Likewise for incRecv and 𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍\mathtt{Received}.

Recall that an actor is either busy (processing a message) or idle (waiting for a message). An actor with knowledge set Φ\Phi is denoted [Φ][\Phi] if it is busy and (Φ)(\Phi) if it is idle.

Our specification includes both system messages (also called control messages) and application messages. The former are automatically generated by the DRL protocol and handled at the system level, whereas the latter are explicitly created and consumed by user-defined behaviors. Application-level messages are denoted 𝚊𝚙𝚙(x,R)\mathtt{app}(x,R). The argument xx is the refob used to send the message. The second argument RR is a set of refobs created by the sender to be used by the destination actor. Any remaining application-specific data in the message is omitted in our notation.

The DRL communication protocol uses two kinds of system messages. 𝚒𝚗𝚏𝚘(y,z,B)\mathtt{info}(y,z,B) is a message sent from an actor AA to an actor CC, informing it that a new refob z:BC{z:B\multimap C} was created using y:AC{y:A\multimap C}. 𝚛𝚎𝚕𝚎𝚊𝚜𝚎(x,n)\mathtt{release}(x,n) is a message sent from an actor AA to an actor BB, informing it that the refob x:AB{x:A\multimap B} has been deactivated and should be released.

A configuration α|μχρ\langle\!\langle\ \alpha\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi} is a quadruple (α,μ,ρ,χ)(\alpha,\mu,\rho,\chi) where: α\alpha is a mapping from actor addresses to knowledge sets; μ\mu is a mapping from actor addresses to multisets of messages; and ρ,χ\rho,\chi are sets of actor addresses. Actors in dom(α)\text{dom}(\alpha) are internal actors and actors in χ\chi are external actors; the two sets may not intersect. The mapping μ\mu associates each actor with undelivered messages to that actor. Actors in ρ\rho are receptionists. We will ensure ρdom(α)\rho\subseteq\text{dom}(\alpha) remains valid in any configuration that is derived from a configuration where the property holds (referred to as the locality laws in [12]).

Configurations are denoted by κ\kappa, κ\kappa^{\prime}, κ0\kappa_{0}, etc. If an actor address AA (resp. a token xx), does not occur in κ\kappa, then the address (resp. the token) is said to be fresh. We assume a facility for generating fresh addresses and tokens.

In order to express our transition rules in a pattern-matching style, we will employ the following shorthand. Let α,[Φ]A\alpha,[\Phi]_{A} refer to a mapping α\alpha^{\prime} where α(A)=[Φ]\alpha^{\prime}(A)=[\Phi] and α=α|dom(α){A}\alpha=\alpha^{\prime}|_{\text{dom}(\alpha^{\prime})\setminus\{A\}}. Similarly, let μ,[Am]\mu,[A\triangleleft m] refer to a mapping μ\mu^{\prime} where mμ(A)m\in\mu^{\prime}(A) and μ=μ|dom(μ){A}{Aμ(A){m}}\mu=\mu^{\prime}|_{\text{dom}(\mu^{\prime})\setminus\{A\}}\cup\{A\mapsto\mu^{\prime}(A)\setminus\{m\}\}. Informally, the expression α,[Φ]A\alpha,[\Phi]_{A} refers to a set of actors containing both α\alpha and the busy actor AA (with knowledge set Φ\Phi); the expression μ,[Am]\mu,[A\triangleleft m] refers to the set of messages containing both μ\mu and the message mm (sent to actor AA).

The rules of our transition system define atomic transitions from one configuration to another. Each transition rule has a label ll, parameterized by some variables x\vec{x} that occur in the left- and right-hand configurations. Given a configuration κ\kappa, these parameters functionally determine the next configuration κ\kappa^{\prime}. Given arguments v\vec{v}, we write κl(v)κ\kappa\xrightarrow{l(\vec{v})}\kappa^{\prime} to denote a semantic step from κ\kappa to κ\kappa^{\prime} using rule l(v)l(\vec{v}).

We refer to a label with arguments l(v)l(\vec{v}) as an event, denoted ee. A sequence of events is denoted π\pi. If π=e1,,en\pi=e_{1},\dots,e_{n} then we write κ𝜋κ\kappa\xrightarrow{\pi}\kappa^{\prime} when κe1κ1e2enκ\kappa\xrightarrow{e_{1}}\kappa_{1}\xrightarrow{e_{2}}\dots\xrightarrow{e_{n}}\kappa^{\prime}. If there exists π\pi such that κ𝜋κ\kappa\xrightarrow{\pi}\kappa^{\prime}, then κ\kappa^{\prime} is derivable from κ\kappa. An execution is a sequence of events e1,,ene_{1},\dots,e_{n} such that κ0e1κ1e2enκn\kappa_{0}\xrightarrow{e_{1}}\kappa_{1}\xrightarrow{e_{2}}\dots\xrightarrow{e_{n}}\kappa_{n}, where κ0\kappa_{0} is the initial configuration (Section 4.2). We say that a property holds at time tt if it holds in κt\kappa_{t}.

4.2 Initial Configuration

The initial configuration κ0\kappa_{0} consists of a single actor in a busy state:

[Φ]A|{E},\langle\!\langle\ [\Phi]_{A}\ |\ \emptyset\ \rangle\!\rangle^{\emptyset}_{\{E\}},

where Φ={𝙰𝚌𝚝𝚒𝚟𝚎(x:AE),𝙲𝚛𝚎𝚊𝚝𝚎𝚍(y:AA),𝙰𝚌𝚝𝚒𝚟𝚎(y:AA)}\Phi=\{\mathtt{Active}({x:A\multimap E}),\ \mathtt{Created}({y:A\multimap A}),\ \mathtt{Active}({y:A\multimap A})\}. The actor’s knowledge set includes a refob to itself and a refob to an external actor EE. AA can become a receptionist by sending EE a refob to itself. Henceforth, we will only consider configurations that are derivable from an initial configuration.

4.3 Standard Actor Operations

Spawn(x,A,B)\textsc{Spawn}(x,A,B)

α,[Φ]A|μχρα,[Φ{𝙰𝚌𝚝𝚒𝚟𝚎(x:AB)}]A,[Ψ]B|μχρ\langle\!\langle\ \alpha,[\Phi]_{A}\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi}\rightarrow\langle\!\langle\ \alpha,[\Phi\cup\{\mathtt{Active}({x:A\multimap B})\}]_{A},[\Psi]_{B}\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi}
where x,y,Bx,y,B fresh
and Ψ={𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x:AB),𝙲𝚛𝚎𝚊𝚝𝚎𝚍(y:BB),𝙰𝚌𝚝𝚒𝚟𝚎(y:BB)}\Psi=\{\mathtt{Created}({x:A\multimap B}),\ \mathtt{Created}({y:B\multimap B}),\ \mathtt{Active}({y:B\multimap B})\}

Send(x,y,z,A,B,C)\textsc{Send}(x,\vec{y},\vec{z},A,B,\vec{C})

α,[Φ]A|μχρα,[incSent(x,Φ)Ψ]A|μ,[B𝚊𝚙𝚙(x,R)]χρ\langle\!\langle\ \alpha,[\Phi]_{A}\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi}\rightarrow\langle\!\langle\ \alpha,[\emph{incSent}(x,\Phi)\cup\Psi]_{A}\ |\ \mu,[B\triangleleft\mathtt{app}(x,R)]\ \rangle\!\rangle^{\rho}_{\chi}
where y\vec{y} and z\vec{z} fresh and n=|y|=|z|=|C|n=|\vec{y}|=|\vec{z}|=|\vec{C}|
and Φ𝙰𝚌𝚝𝚒𝚟𝚎(x:AB)\Phi\vdash\mathtt{Active}({x:A\multimap B}) and in,Φ𝙰𝚌𝚝𝚒𝚟𝚎(yi:ACi)\forall i\leq n,\ \Phi\vdash\mathtt{Active}({y_{i}:A\multimap C_{i}})
and R={zi:BCi|in}R=\{{z_{i}:B\multimap C_{i}}\ |\ i\leq n\} and Ψ={𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(yi,zi)|in}\Psi=\{\mathtt{CreatedUsing}(y_{i},z_{i})\ |\ i\leq n\}

Receive(x,B,R)\textsc{Receive}(x,B,R)

α,(Φ)B|μ,[B𝚊𝚙𝚙(x,R)]χρα,[incRecv(x,Φ)Ψ]B|μχρ\langle\!\langle\ \alpha,(\Phi)_{B}\ |\ \mu,[B\triangleleft\mathtt{app}(x,R)]\ \rangle\!\rangle^{\rho}_{\chi}\rightarrow\langle\!\langle\ \alpha,[\emph{incRecv}(x,\Phi)\cup\Psi]_{B}\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi}
where Ψ={𝙰𝚌𝚝𝚒𝚟𝚎(z)|zR}\Psi=\{\mathtt{Active}(z)\ |\ z\in R\}

Idle(A)\textsc{Idle}(A)

α,[Φ]A|μχρα,(Φ)A|μχρ\langle\!\langle\ \alpha,[\Phi]_{A}\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi}\rightarrow\langle\!\langle\ \alpha,(\Phi)_{A}\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi}
Figure 4: Rules for standard actor interactions.

Fig. 4 gives transition rules for standard actor operations, such as spawning actors and sending messages. Each of these rules corresponds a rule in the standard operational semantics of actors [3]. Note that each rule is atomic, but can just as well be implemented as a sequence of several smaller steps without loss of generality because actors do not share state – see [3] for a formal proof.

The Spawn event allows a busy actor AA to spawn a new actor BB and creates two refobs x:AB,y:BB{x:A\multimap B},\ {y:B\multimap B}. BB is initialized with knowledge about xx and yy via the facts 𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x),𝙲𝚛𝚎𝚊𝚝𝚎𝚍(y)\mathtt{Created}(x),\mathtt{Created}(y). The facts 𝙰𝚌𝚝𝚒𝚟𝚎(x),𝙰𝚌𝚝𝚒𝚟𝚎(y)\mathtt{Active}(x),\mathtt{Active}(y) allow AA and BB to immediately begin sending messages to BB. Note that implementing Spawn does not require a synchronization protocol between AA and BB to construct x:AB{x:A\multimap B}. The parent AA can pass both its address and the freshly generated token xx to the constructor for BB. Since actors typically know their own addresses, this allows BB to construct the triple (x,A,B)(x,A,B). Since the spawn call typically returns the address of the spawned actor, AA can also create the same triple.

The Send event allows a busy actor AA to send an application-level message to BB containing a set of refobs z1,,znz_{1},\dots,z_{n} to actors C=C1,,Cn\vec{C}=C_{1},\dots,C_{n} – it is possible that B=AB=A or Ci=AC_{i}=A for some ii. For each new refob ziz_{i}, we say that the message contains ziz_{i}. Any other data in the message besides these refobs is irrelevant to termination detection and therefore omitted. To send the message, AA must have active refobs to both the target actor BB and to every actor C1,,CnC_{1},\dots,C_{n} referenced in the message. For each target CiC_{i}, AA adds a fact 𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(yi,zi)\mathtt{CreatedUsing}(y_{i},z_{i}) to its knowledge set; we say that AA created ziz_{i} using yiy_{i}. Finally, AA must increment its 𝚂𝚎𝚗𝚝\mathtt{Sent} count for the refob xx used to send the message; we say that the message is sent along xx.

The Receive event allows an idle actor BB to become busy by consuming an application message sent to BB. Before performing subsequent actions, BB increments the receive count for xx and adds all refobs in the message to its knowledge set.

Finally, the Idle event puts a busy actor into the idle state, enabling it to consume another message.

4.4 Release Protocol

SendInfo(y,z,A,B,C)\textsc{SendInfo}(y,z,A,B,C)

α,[ΦΨ]A|μχρα,[incSent(y,Φ)]A|μ,[C𝚒𝚗𝚏𝚘(y,z,B)]χρ\langle\!\langle\ \alpha,[\Phi\cup\Psi]_{A}\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi}\rightarrow\langle\!\langle\ \alpha,[\emph{incSent}(y,\Phi)]_{A}\ |\ \mu,[C\triangleleft\mathtt{info}(y,z,B)]\ \rangle\!\rangle^{\rho}_{\chi}
where Ψ={𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(y:AC,z:BC)}\Psi=\{\mathtt{CreatedUsing}({y:A\multimap C},{z:B\multimap C})\}

Info(y,z,B,C)\textsc{Info}(y,z,B,C)

α,(Φ)C|μ,[C𝚒𝚗𝚏𝚘(y,z,B)]χρα,(incRecv(y,Φ)Ψ)C|μχρ\langle\!\langle\ \alpha,(\Phi)_{C}\ |\ \mu,[C\triangleleft\mathtt{info}(y,z,B)]\ \rangle\!\rangle^{\rho}_{\chi}\rightarrow\langle\!\langle\ \alpha,(\emph{incRecv}(y,\Phi)\cup\Psi)_{C}\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi}
where Ψ={𝙲𝚛𝚎𝚊𝚝𝚎𝚍(z:BC)}\Psi=\{\mathtt{Created}({z:B\multimap C})\}

SendRelease(x,A,B)\textsc{SendRelease}(x,A,B)

α,[ΦΨ]A|μχρα,[Φ]A|μ,[B𝚛𝚎𝚕𝚎𝚊𝚜𝚎(x,n)]χρ\langle\!\langle\ \alpha,[\Phi\cup\Psi]_{A}\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi}\rightarrow\langle\!\langle\ \alpha,[\Phi]_{A}\ |\ \mu,[B\triangleleft\mathtt{release}(x,n)]\ \rangle\!\rangle^{\rho}_{\chi}
where Ψ={𝙰𝚌𝚝𝚒𝚟𝚎(x:AB),𝚂𝚎𝚗𝚝(x,n)}\Psi=\{\mathtt{Active}({x:A\multimap B}),\mathtt{Sent}(x,n)\}
and y,𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(x,y)Φ\not\exists y,\ \mathtt{CreatedUsing}(x,y)\in\Phi

Release(x,A,B)\textsc{Release}(x,A,B)

α,(Φ)B|μ,[B𝚛𝚎𝚕𝚎𝚊𝚜𝚎(x,n)]χρα,(Φ{𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x)})B|μχρ\langle\!\langle\ \alpha,(\Phi)_{B}\ |\ \mu,[B\triangleleft\mathtt{release}(x,n)]\ \rangle\!\rangle^{\rho}_{\chi}\rightarrow\langle\!\langle\ \alpha,(\Phi\cup\{\mathtt{Released}(x)\})_{B}\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi}
only if Φ𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍(x,n)\Phi\vdash\mathtt{Received}(x,n)

Compaction(x,B,C)\textsc{Compaction}(x,B,C)

α,(ΦΨ)C|μχρα,(Φ)C|μχρ\langle\!\langle\ \alpha,(\Phi\cup\Psi)_{C}\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi}\rightarrow\langle\!\langle\ \alpha,(\Phi)_{C}\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi}
where Ψ={𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x:BC),𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x:BC),𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍(x,n)}\Psi=\{\mathtt{Created}({x:B\multimap C}),\mathtt{Released}({x:B\multimap C}),\mathtt{Received}(x,n)\} for some nn\in\mathbb{N}
or Ψ={𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x:BC),𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x:BC)}\Psi=\{\mathtt{Created}({x:B\multimap C}),\mathtt{Released}({x:B\multimap C})\} and n,𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍(x,n)Φ\forall n\in\mathbb{N},\ \mathtt{Received}(x,n)\not\in\Phi

Snapshot(A,Φ)\textsc{Snapshot}(A,\Phi)

α,(Φ)A|μχρα,(Φ)A|μχρ\langle\!\langle\ \alpha,(\Phi)_{A}\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi}\rightarrow\langle\!\langle\ \alpha,(\Phi)_{A}\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi}
Figure 5: Rules for performing the release protocol.

Whenever an actor creates or receives a refob, it adds facts to its knowledge set. To remove these facts when they are no longer needed, actors can perform the release protocol defined in Fig. 5. All of these rules are not present in the standard operational semantics of actors.

The SendInfo event allows a busy actor AA to inform CC about a refob z:BC{z:B\multimap C} that it created using yy; we say that the 𝚒𝚗𝚏𝚘\mathtt{info} message is sent along yy and contains zz. This event allows AA to remove the fact 𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(y,z)\mathtt{CreatedUsing}(y,z) from its knowledge set. It is crucial that AA also increments its 𝚂𝚎𝚗𝚝\mathtt{Sent} count for yy to indicate an undelivered 𝚒𝚗𝚏𝚘\mathtt{info} message sent to CC: it allows the snapshot aggregator to detect when there are undelivered 𝚒𝚗𝚏𝚘\mathtt{info} messages, which contain refobs. This message is delivered with the Info event, which adds the fact 𝙲𝚛𝚎𝚊𝚝𝚎𝚍(z:BC)\mathtt{Created}({z:B\multimap C}) to CC’s knowledge set and correspondingly increments CC’s 𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍\mathtt{Received} count for yy.

When an actor AA no longer needs x:AB{x:A\multimap B} for sending messages, AA can deactivate xx with the SendRelease event; we say that the 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release} is sent along xx. A precondition of this event is that AA has already sent messages to inform BB about all the refobs it has created using xx. In practice, an implementation may defer sending any 𝚒𝚗𝚏𝚘\mathtt{info} or 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release} messages to a target BB until all AA’s refobs to BB are deactivated. This introduces a trade-off between the number of control messages and the rate of simple garbage detection (Section 5).

Each 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release} message for a refob xx includes a count nn of the number of messages sent using xx. This ensures that 𝚛𝚎𝚕𝚎𝚊𝚜𝚎(x,n)\mathtt{release}(x,n) is only delivered after all the preceding messages sent along xx have been delivered. Once the Release event can be executed, it adds the fact that xx has been released to BB’s knowledge set. Once CC has received both an 𝚒𝚗𝚏𝚘\mathtt{info} and 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release} message for a refob xx, it may remove facts about xx from its knowledge set using the Compaction event.

Finally, the Snapshot event captures an idle actor’s knowledge set. For simplicity, we have omitted the process of disseminating snapshots to an aggregator. Although this event does not change the configuration, it allows us to prove properties about snapshot events at different points in time.

4.5 Composition and Effects

In(A,R)\textsc{In}(A,R)

α|μχρα|μ,[A𝚊𝚙𝚙(𝚗𝚞𝚕𝚕,R)]χχρ\langle\!\langle\ \alpha\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi}\rightarrow\langle\!\langle\ \alpha\ |\ \mu,[A\triangleleft\mathtt{app}(\mathtt{null},R)]\ \rangle\!\rangle^{\rho}_{\chi\cup\chi^{\prime}}
where AρA\in\rho and R={x1:AB1,,xn:ABn}R=\{{x_{1}:A\multimap B_{1}},\dots,{x_{n}:A\multimap B_{n}}\} and x1,,xnx_{1},\dots,x_{n} fresh
and {B1,,Bn}dom(α)ρ\{B_{1},\dots,B_{n}\}\cap\text{dom}(\alpha)\subseteq\rho and χ={B1,,Bn}dom(α)\chi^{\prime}=\{B_{1},\dots,B_{n}\}\setminus\text{dom}(\alpha)

Out(x,B,R)\textsc{Out}(x,B,R)

α|μ,[B𝚊𝚙𝚙(x,R)]χρα|μχρρ\langle\!\langle\ \alpha\ |\ \mu,[B\triangleleft\mathtt{app}(x,R)]\ \rangle\!\rangle^{\rho}_{\chi}\rightarrow\langle\!\langle\ \alpha\ |\ \mu\ \rangle\!\rangle^{\rho\cup\rho^{\prime}}_{\chi}
where BχB\in\chi and R={x1:BC1,,xn:BCn}R=\{{x_{1}:B\multimap C_{1}},\dots,{x_{n}:B\multimap C_{n}}\} and ρ={C1,,Cn}dom(α)\rho^{\prime}=\{C_{1},\dots,C_{n}\}\cap\text{dom}(\alpha)

ReleaseOut(x,B)\textsc{ReleaseOut}(x,B)

α|μ,[B𝚛𝚎𝚕𝚎𝚊𝚜𝚎(x,n)]χ{B}ρα|μχ{B}ρ\langle\!\langle\ \alpha\ |\ \mu,[B\triangleleft\mathtt{release}(x,n)]\ \rangle\!\rangle^{\rho}_{\chi\cup\{B\}}\rightarrow\langle\!\langle\ \alpha\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi\cup\{B\}}

InfoOut(y,z,A,B,C)\textsc{InfoOut}(y,z,A,B,C)

α|μ,[C𝚒𝚗𝚏𝚘(y,z,A,B)]χ{C}ρα|μχ{C}ρ\langle\!\langle\ \alpha\ |\ \mu,[C\triangleleft\mathtt{info}(y,z,A,B)]\ \rangle\!\rangle^{\rho}_{\chi\cup\{C\}}\rightarrow\langle\!\langle\ \alpha\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi\cup\{C\}}
Figure 6: Rules for interacting with the outside world.

We give rules to dictate how internal actors interact with external actors in Fig. 6. The In and Out rules correspond to similar rules in the standard operational semantics of actors.

Since internal garbage collection protocols are not exposed to the outside world, all 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release} and 𝚒𝚗𝚏𝚘\mathtt{info} messages sent to external actors are simply dropped by the ReleaseOut and InfoOut events. Likewise, only 𝚊𝚙𝚙\mathtt{app} messages can enter the system. Since we cannot statically determine when a receptionist’s address has been forgotten by all external actors, we assume that receptionists are never terminated. The resulting “black box” behavior of our system is the same as the actor systems in [3]. Hence, in principle DRL can be gradually integrated into a codebase by creating a subsystem for garbage-collected actors.

The In event allows an external actor to send an application-level message to a receptionist AA containing a set of refobs RR, all owned by AA. Since external actors do not use refobs, the message is sent using the special 𝚗𝚞𝚕𝚕\mathtt{null} token. All targets in RR that are not internal actors are added to the set of external actors.

The Out event delivers an application-level message to an external actor with a set of refobs RR. All internal actors referenced in RR become receptionists because their addresses have been exposed to the outside world.

4.6 Garbage

We can now operationally characterize actor garbage in our model. An actor AA can potentially receive a message in κ\kappa if there is a sequence of events (possibly of length zero) leading from κ\kappa to a configuration κ\kappa^{\prime} in which AA has an undelivered message. We say that an actor is terminated if it is idle and cannot potentially receive a message.

An actor is blocked if it satisfies three conditions: (1) it is idle, (2) it is not a receptionist, and (3) it has no undelivered messages; otherwise, it is unblocked. We define potential reachability as the reflexive transitive closure of the potential acquaintance relation. That is, A1A_{1} can potentially reach AnA_{n} if and only if there is a sequence of unreleased refobs (x1:A1A2),,(xn:An1An)({x_{1}:A_{1}\multimap A_{2}}),\dots,({x_{n}:A_{n-1}\multimap A_{n}}); recall that a refob x:AB{x:A\multimap B} is unreleased if its target BB has not yet received a 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release} message for xx.

Notice that an actor can potentially receive a message if and only if it is potentially reachable from an unblocked actor. Hence an actor is terminated if and only if it is only potentially reachable by blocked actors. A special case of this is simple garbage, in which an actor is blocked and has no potential inverse acquaintances besides itself.

We say that a set of actors SS is closed (with respect to the potential inverse acquaintance relation) if, whenever BSB\in S and there is an unreleased refob x:AB{x:A\multimap B}, then also ASA\in S. Notice that the closure of a set of terminated actors is also a set of terminated actors.

5 Chain Lemma

To determine if an actor has terminated, one must show that all of its potential inverse acquaintances have terminated. This appears to pose a problem for termination detection, since actors cannot have a complete listing of all their potential inverse acquaintances without some synchronization: actors would need to consult their acquaintances before creating new references to them. In this section, we show that the DRL protocol provides a weaker guarantee that will nevertheless prove sufficient: knowledge about an actor’s refobs is distributed across the system and there is always a “path” from the actor to any of its potential inverse acquaintances.

mmBBAACCFFDDEEAABusyReferenceMessagemmAAIdleBBAACCFFDDEE(1)(2)AATerminatedCCAAyyCCAABBxxyyCCAABBxxyy𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(y,z)\mathtt{CreatedUsing}(y,z)𝚊𝚙𝚙(x,{z})\mathtt{app}(x,\{z\})CCAABBxxyy𝙰𝚌𝚝𝚒𝚟𝚎(z)\mathtt{Active}(z)𝚒𝚗𝚏𝚘(y,z)\mathtt{info}(y,z)CCAABBxxyy𝙲𝚛𝚎𝚊𝚝𝚎𝚍(z)\mathtt{Created}(z)𝚛𝚎𝚕𝚎𝚊𝚜𝚎(z)\mathtt{release}(z)CCAABBxxyy𝙲𝚛𝚎𝚊𝚝𝚎𝚍(z)\mathtt{Created}(z)𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(z)\mathtt{Released}(z)AAxxmm(2)(4)(6)(1)(3)(5)zzAABusy ActorReferenceMessageIdle ActorAABBCCt1t_{1}t0t_{0}𝚊𝚙𝚙(x)\mathtt{app}(x)𝚊𝚙𝚙(y)\mathtt{app}(y)𝚛𝚎𝚕𝚎𝚊𝚜𝚎(y)\mathtt{release}(y)𝚊𝚙𝚙(y)\mathtt{app}(y^{\prime})t2t_{2}t3t_{3}𝚊𝚙𝚙(x)\mathtt{app}(x)𝚊𝚙𝚙(x,{y})\mathtt{app}(x,\{y^{\prime}\})𝚂𝚎𝚗𝚝(y,1)\mathtt{Sent}(y,1)𝚂𝚎𝚗𝚝(y,2)\mathtt{Sent}(y,2)𝚂𝚎𝚗𝚝(y,1)\mathtt{Sent}(y^{\prime},1)\emptyset𝚁𝚎𝚌𝚟(y,1)\mathtt{Recv}(y,1)𝚁𝚎𝚌𝚟(y,2)\mathtt{Recv}(y,2)𝚁𝚎𝚌𝚟(y,1)\mathtt{Recv}(y^{\prime},1)\emptysetA2A_{2}A1A_{1}𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x1)\mathtt{Created}(x_{1})(2)(1)A3A_{3}𝚊𝚙𝚙(y,{x3})\mathtt{app}(y,\{x_{3}\})BB𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(x1,x2)\mathtt{CreatedUsing}(x_{1},x_{2})𝚒𝚗𝚏𝚘(x2,x3)\mathtt{info}(x_{2},x_{3})A2A_{2}A1A_{1}𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x1)\mathtt{Created}(x_{1})A3A_{3}𝚊𝚙𝚙(y,{x3})\mathtt{app}(y,\{x_{3}\})BB𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(x1,x2)\mathtt{CreatedUsing}(x_{1},x_{2})𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(x2,x3)\mathtt{CreatedUsing}(x_{2},x_{3})x1x_{1}x2x_{2}x2x_{2}x1x_{1}
Figure 7: An example of a chain from BB to x3x_{3}.

Let us construct a concrete example of such a path, depicted by Fig. 7. Suppose that A1A_{1} spawns BB, gaining a refob x1:A1B{x_{1}:A_{1}\multimap B}. Then A1A_{1} may use x1x_{1} to create x2:A2B{x_{2}:A_{2}\multimap B}, which A2A_{2} may receive and then use x2x_{2} to create x3:A3B{x_{3}:A_{3}\multimap B}.

At this point, there are unreleased refobs owned by A2A_{2} and A3A_{3} that are not included in BB’s knowledge set. However, Fig. 7 shows that the distributed knowledge of B,A1,A2B,A_{1},A_{2} creates a “path” to all of BB’s potential inverse acquaintances. Since A1A_{1} spawned BB, BB knows the fact 𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x1)\mathtt{Created}(x_{1}). Then when A1A_{1} created x2x_{2}, it added the fact 𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(x1,x2)\mathtt{CreatedUsing}(x_{1},x_{2}) to its knowledge set, and likewise A2A_{2} added the fact 𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(x2,x3)\mathtt{CreatedUsing}(x_{2},x_{3}); each fact points to another actor that owns an unreleased refob to BB (Fig. 7 (1)).

Since actors can remove 𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐\mathtt{CreatedUsing} facts by sending 𝚒𝚗𝚏𝚘\mathtt{info} messages, we also consider (Fig. 7 (2)) to be a “path” from BB to A3A_{3}. But notice that, once BB receives the 𝚒𝚗𝚏𝚘\mathtt{info} message, the fact 𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x3)\mathtt{Created}(x_{3}) will be added to its knowledge set and so there will be a “direct path” from BB to A3A_{3}. We formalize this intuition with the notion of a chain in a given configuration α|μχρ\langle\!\langle\ \alpha\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi}:

Definition 5.1.

A chain to x:AB{x:A\multimap B} is a sequence of unreleased refobs (x1:A1B),,(xn:AnB)({x_{1}:A_{1}\multimap B}),\allowbreak\dots,\allowbreak({x_{n}:A_{n}\multimap B}) such that:

  • α(B)𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x1:A1B)\alpha(B)\vdash\mathtt{Created}({x_{1}:A_{1}\multimap B});

  • For all i<ni<n, either α(Ai)𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(xi,xi+1)\alpha(A_{i})\vdash\mathtt{CreatedUsing}(x_{i},x_{i+1}) or the message [B𝚒𝚗𝚏𝚘(xi,xi+1)][B\triangleleft\mathtt{info}(x_{i},x_{i+1})] is in transit; and

  • An=AA_{n}=A and xn=xx_{n}=x.

We say that an actor BB is in the root set if it is a receptionist or if there is an application message 𝚊𝚙𝚙(x,R)\mathtt{app}(x,R) in transit to an external actor with Btargets(R)B\in\text{targets}(R). Since external actors never release refobs, actors in the root set must never terminate.

Lemma 5.2 (Chain Lemma).

Let BB be an internal actor in κ\kappa. If BB is not in the root set, then there is a chain to every unreleased refob x:AB{x:A\multimap B}. Otherwise, there is a chain to some refob y:CB{y:C\multimap B} where CC is an external actor.

{remark*}

When BB is in the root set, not all of its unreleased refobs are guaranteed to have chains. This is because an external actor may send BB’s address to other receptionists without sending an 𝚒𝚗𝚏𝚘\mathtt{info} message to BB.

An immediate application of the Chain Lemma is to allow actors to detect when they are simple garbage. If any actor besides BB owns an unreleased refob to BB, then BB must have a fact 𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x:AB)\mathtt{Created}({x:A\multimap B}) in its knowledge set where ABA\neq B. Hence, if BB has no such facts, then it must have no nontrivial potential inverse acquaintances. Moreover, since actors can only have undelivered messages along unreleased refobs, BB also has no undelivered messages from any other actor; it can only have undelivered messages that it sent to itself. This gives us the following result:

Theorem 5.3.

Suppose BB is idle with knowledge set Φ\Phi, such that:

  • Φ\Phi does not contain any facts of the form 𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x:AB)\mathtt{Created}({x:A\multimap B}) where ABA\neq B; and

  • for all facts 𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x:BB)Φ\mathtt{Created}({x:B\multimap B})\in\Phi, also Φ𝚂𝚎𝚗𝚝(x,n)𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍(x,n)\Phi\vdash\mathtt{Sent}(x,n)\land\mathtt{Received}(x,n) for some nn.

Then BB is simple garbage.

6 Termination Detection

In order to detect non-simple terminated garbage, actors periodically sends a snapshot of their knowledge set to a snapshot aggregator actor. An aggregator in turn may disseminate snapshots it has to other aggregators. Each aggregator maintains a map data structure, associating an actor’s address to its most recent snapshot; in effect, snapshot aggregators maintain an eventually consistent key-value store with addresses as keys and snapshots as values. At any time, an aggregator can scan its local store to find terminated actors and send them a request to self-destruct.

Given an arbitrary set of snapshots QQ, we characterize the finalized subsets of QQ in this section. We show that the actors that took these finalized snapshots must be terminated. Conversely, the snapshots of any closed set of terminated actors are guaranteed to be finalized. (Recall that the closure of a set of terminated actors is also a terminated set of actors.) Thus, snapshot aggregators can eventually detect all terminated actors by periodically searching their local stores for finalized subsets. Finally, we give an algorithm for obtaining the maximum finalized subset of a set QQ by “pruning away” the snapshots of actors that appear not to have terminated.

Recall that when we speak of a set of snapshots QQ, we assume each snapshot was taken by a different actor. We will write ΦAQ\Phi_{A}\in Q to denote AA’s snapshot in QQ; we will also write AQA\in Q if AA has a snapshot in QQ. We will also write QϕQ\vdash\phi if Φϕ\Phi\vdash\phi for some ΦQ\Phi\in Q.

Definition 6.1.

A set of snapshots QQ is closed if, whenever Q𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x:AB)Q\vdash\mathtt{Unreleased}({x:A\multimap B}) and BQB\in Q, then also AQA\in Q and ΦA𝙰𝚌𝚝𝚒𝚟𝚎(x:AB)\Phi_{A}\vdash\mathtt{Active}({x:A\multimap B}).

Definition 6.2.

An actor BQB\in Q appears blocked if, for every Q𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x:AB)Q\vdash\mathtt{Unreleased}({x:A\multimap B}), then ΦA,ΦBQ\Phi_{A},\Phi_{B}\in Q and ΦA𝚂𝚎𝚗𝚝(x,n)\Phi_{A}\vdash\mathtt{Sent}(x,n) and ΦB𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍(x,n)\Phi_{B}\vdash\mathtt{Received}(x,n) for some nn.

Definition 6.3.

A set of snapshots QQ is finalized if it is closed and every actor in QQ appears blocked.

This definition corresponds to our characterization in Section 4.6: An actor is terminated precisely when it is in a closed set of blocked actors.

Theorem 6.4 (Safety).

If QQ is a finalized set of snapshots at time tft_{f} then the actors in QQ are all terminated at tft_{f}.

We say that the final action of a terminated actor is the last non-snapshot event it performs before becoming terminated. Notice that an actor’s final action can only be an Idle, Info, or Release event. Note also that the final action may come strictly before an actor becomes terminated, since a blocked actor may only terminate after all of its potential inverse acquaintances become blocked.

The following lemma allows us to prove that DRL is eventually live. It also shows that an non-finalized set of snapshots must have an unblocked actor.

Lemma 6.5.

Let SS be a closed set of terminated actors at time tft_{f}. If every actor in SS took a snapshot sometime after its final action, then the resulting set of snapshots is finalized.

Theorem 6.6 (Liveness).

If every actor eventually takes a snapshot after performing an Idle, Info, or Release event, then every terminated actor is eventually part of a finalized set of snapshots.

Proof 6.7.

If an actor AA is terminated, then the closure SS of {A}\{A\} is a terminated set of actors. Since every actor eventually takes a snapshot after taking its final action, Lemma 6.5 implies that the resulting snapshots of SS are finalized.

We say that a refob x:AB{x:A\multimap B} is unreleased in QQ if Q𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x)Q\vdash\mathtt{Unreleased}(x). Such a refob is said to be relevant when BQB\in Q implies AQA\in Q and ΦA𝙰𝚌𝚝𝚒𝚟𝚎(x)\Phi_{A}\vdash\mathtt{Active}(x) and ΦA𝚂𝚎𝚗𝚝(x,n)\Phi_{A}\vdash\mathtt{Sent}(x,n) and ΦB𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍(x,n)\Phi_{B}\vdash\mathtt{Received}(x,n) for some nn; intuitively, this indicates that BB has no undelivered messages along xx. Notice that a set QQ is finalized if and only if all unreleased refobs in QQ are relevant.

Observe that if x:AB{x:A\multimap B} is unreleased and irrelevant in QQ, then BB cannot be in any finalized subset of QQ. We can therefore employ a simple iterative algorithm to find the maximum finalized subset of QQ: for each irrelevant unreleased refob x:AB{x:A\multimap B} in QQ, remove the target BB from QQ. Since this can make another unreleased refob y:BC{y:B\multimap C} irrelevant, we must repeat this process until a fixed point is reached. In the resulting subset QQ^{\prime}, all unreleased refobs are relevant. Since all actors in QQQ\setminus Q^{\prime} are not members of any finalized subset of QQ, it must be that QQ^{\prime} is the maximum finalized subset of QQ.

7 Conclusion and Future Work

We have shown how deferred reference listing and message counts can be used to detect termination in actor systems. The technique is provably safe (Theorem 6.4) and eventually live (Theorem 6.6). An implementation in Akka is presently underway.

We believe that DRL satisfies our three initial goals:

  1. 1.

    Termination detection does not restrict concurrency in the application. Actors do not need to coordinate their snapshots or pause execution during garbage collection.

  2. 2.

    Termination detection does not impose high overhead. The amortized memory overhead of our technique is linear in the number of unreleased refobs. Besides application messages, the only additional control messages required by the DRL communication protocol are 𝚒𝚗𝚏𝚘\mathtt{info} and 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release} messages. These control messages can be batched together and deferred, at the cost of worse termination detection time.

  3. 3.

    Termination detection scales with the number of nodes in the system. Our algorithm is incremental, decentralized, and does not require synchronization between nodes.

Since it does not matter what order snapshots are collected in, DRL can be used as a “building block” for more sophisticated garbage collection algorithms. One promising direction is to take a generational approach [15], in which long-lived actors take snapshots less frequently than short-lived actors. Different types of actors could also take snapshots at different rates. In another approach, snapshot aggregators could request snapshots instead of waiting to receive them.

In the presence of faults, DRL remains safe but its liveness properties are affected. If an actor AA crashes and its state cannot be recovered, then none of its refobs can be released and the aggregator will never receive its snapshot. Consequently, all actors potentially reachable from AA can no longer be garbage collected. However, AA’s failure does not affect the garbage collection of actors it cannot reach. In particular, network partitions between nodes will not delay node-local garbage collection.

Choosing an adequate fault-recovery protocol will likely vary depending on the target actor framework. One option is to use checkpointing or event-sourcing to persist GC state; the resulting overhead may be acceptable in applications that do not frequently spawn actors or create refobs. Another option is to monitor actors for failure and infer which refobs are no longer active; this is a subject for future work.

Another issue that can affect liveness is message loss: If any messages along a refob x:AB{x:A\multimap B} are dropped, then BB can never be garbage collected because it will always appear unblocked. This is, in fact, the desired behavior if one cannot guarantee that the message will not be delivered at some later point. In practice, this problem might be addressed with watermarking.

References

  • [1] Gul Agha. ACTORS - a Model of Concurrent Computation in Distributed Systems. MIT Press Series in Artificial Intelligence. MIT Press, 1990.
  • [2] Gul Agha. Concurrent object-oriented programming. Communications of the ACM, 33(9):125–141, September 1990.
  • [3] Gul A. Agha, Ian A. Mason, Scott F. Smith, and Carolyn L. Talcott. A foundation for actor computation. Journal of Functional Programming, 7(1):1–72, January 1997. doi:10.1017/S095679689700261X.
  • [4] Akka. https://akka.io/.
  • [5] Joe Armstrong, Robert Virding, Claes Wikström, and Mike Williams. Concurrent Programming in ERLANG. Prentice Hall, Englewood Cliffs, New Jersey, second edition, 1996.
  • [6] Di Bevan. Distributed garbage collection using reference counting. In G. Goos, J. Hartmanis, D. Barstow, W. Brauer, P. Brinch Hansen, D. Gries, D. Luckham, C. Moler, A. Pnueli, G. Seegmüller, J. Stoer, N. Wirth, J. W. Bakker, A. J. Nijman, and P. C. Treleaven, editors, PARLE Parallel Architectures and Languages Europe, volume 259, pages 176–187. Springer Berlin Heidelberg, Berlin, Heidelberg, 1987. doi:10.1007/3-540-17945-3_10.
  • [7] Sebastian Blessing, Sylvan Clebsch, and Sophia Drossopoulou. Tree topologies for causal message delivery. In Proceedings of the 7th ACM SIGPLAN International Workshop on Programming Based on Actors, Agents, and Decentralized Control - AGERE 2017, pages 1–10, Vancouver, BC, Canada, 2017. ACM Press. doi:10.1145/3141834.3141835.
  • [8] Sergey Bykov, Alan Geller, Gabriel Kliot, James R. Larus, Ravi Pandya, and Jorgen Thelin. Orleans: Cloud computing for everyone. In Proceedings of the 2nd ACM Symposium on Cloud Computing - SOCC ’11, pages 1–14, Cascais, Portugal, 2011. ACM Press. doi:10.1145/2038916.2038932.
  • [9] K. Mani Chandy and Leslie Lamport. Distributed snapshots: Determining global states of distributed systems. ACM Transactions on Computer Systems, 3(1):63–75, February 1985. doi:10.1145/214451.214456.
  • [10] Sylvan Clebsch and Sophia Drossopoulou. Fully concurrent garbage collection of actors on many-core machines. In Proceedings of the 2013 ACM SIGPLAN International Conference on Object Oriented Programming Systems Languages & Applications - OOPSLA ’13, pages 553–570, Indianapolis, Indiana, USA, 2013. ACM Press. doi:10.1145/2509136.2509557.
  • [11] Colin J Fidge. Timestamps in message-passing systems that preserve the partial ordering. Australian Computer Science Communications, 10(1):56–66, February 1988.
  • [12] Carl Hewitt and Henry G. Baker. Laws for communicating parallel processes. In Bruce Gilchrist, editor, Information Processing, Proceedings of the 7th IFIP Congress 1977, Toronto, Canada, August 8-12, 1977, pages 987–992. North-Holland, 1977.
  • [13] D. Kafura, M. Mukherji, and D.M. Washabaugh. Concurrent and distributed garbage collection of active objects. IEEE Transactions on Parallel and Distributed Systems, 6(4):337–350, April 1995. doi:10.1109/71.372788.
  • [14] Ten-Hwang Lai. Termination detection for dynamically distributed systems with non-first-in-first-out communication. Journal of Parallel and Distributed Computing, 3(4):577–599, December 1986. doi:10.1016/0743-7315(86)90015-8.
  • [15] Henry Lieberman and Carl Hewitt. A real-time garbage collector based on the lifetimes of objects. Commun. ACM, 26(6):419–429, 1983. doi:10.1145/358141.358147.
  • [16] Jeff Matocha and Tracy Camp. A taxonomy of distributed termination detection algorithms. Journal of Systems and Software, 43(3):207–221, November 1998. doi:10.1016/S0164-1212(98)10034-1.
  • [17] Friedemann Mattern. Algorithms for distributed termination detection. Distributed Computing, 2(3):161–175, September 1987. doi:10.1007/BF01782776.
  • [18] NHS to Deploy Riak for New IT Backbone With Quality of Care Improvements in Sight. https://riak.com/nhs-to-deploy-riak-for-new-it-backbone-with-quality-of-care-improvements-in-sight.html, October 2013.
  • [19] PayPal Blows Past 1 Billion Transactions Per Day Using Just 8 VMs With Akka, Scala, Kafka and Akka Streams. https://www.lightbend.com/case-studies/paypal-blows-past-1-billion-transactions-per-day-using-just-8-vms-and-akka-scala-kafka-and-akka-streams.
  • [20] José M. Piquer. Indirect Reference Counting: A Distributed Garbage Collection Algorithm. In Emile H. L. Aarts, Jan van Leeuwen, and Martin Rem, editors, Parle ’91 Parallel Architectures and Languages Europe, volume 505, pages 150–165. Springer Berlin Heidelberg, Berlin, Heidelberg, 1991. doi:10.1007/978-3-662-25209-3_11.
  • [21] David Plainfossé and Marc Shapiro. A survey of distributed garbage collection techniques. In Memory Management, International Workshop IWMM 95, Kinross, UK, September 27-29, 1995, Proceedings, pages 211–249, 1995. doi:10.1007/3-540-60368-9\\_26.
  • [22] Dan Plyukhin and Gul Agha. Concurrent garbage collection in the actor model. In Proceedings of the 8th ACM SIGPLAN International Workshop on Programming Based on Actors, Agents, and Decentralized Control - AGERE 2018, pages 44–53, Boston, MA, USA, 2018. ACM Press. doi:10.1145/3281366.3281368.
  • [23] M. Schelvis. Incremental distribution of timestamp packets: A new approach to distributed garbage collection. In Conference Proceedings on Object-Oriented Programming Systems, Languages and Applications - OOPSLA ’89, pages 37–48, New Orleans, Louisiana, United States, 1989. ACM Press. doi:10.1145/74877.74883.
  • [24] Abhay Vardhan and Gul Agha. Using passive object garbage collection algorithms for garbage collection of active objects. ACM SIGPLAN Notices, 38(2 supplement):106, February 2003. doi:10.1145/773039.512443.
  • [25] Nalini Venkatasubramanian, Gul Agha, and Carolyn Talcott. Scalable distributed garbage collection for systems of active objects. In Yves Bekkers and Jacques Cohen, editors, Memory Management, volume 637, pages 134–147. Springer-Verlag, Berlin/Heidelberg, 1992. doi:10.1007/BFb0017187.
  • [26] Nalini Venkatasubramanian and Carolyn Talcott. Reasoning about meta level activities in open distributed systems. In Proceedings of the Fourteenth Annual ACM Symposium on Principles of Distributed Computing - PODC ’95, pages 144–152, Ottowa, Ontario, Canada, 1995. ACM Press. doi:10.1145/224964.224981.
  • [27] Stanislav Vishnevskiy. How Discord Scaled Elixir to 5,000,000 Concurrent Users. https://blog.discord.com/scaling-elixir-f9b8e1e7c29b, July 2017.
  • [28] Wei-Jen Wang. Conservative snapshot-based actor garbage collection for distributed mobile actor systems. Telecommunication Systems, June 2011. doi:10.1007/s11235-011-9509-1.
  • [29] Wei-Jen Wang, Carlos Varela, Fu-Hau Hsu, and Cheng-Hsien Tang. Actor Garbage Collection Using Vertex-Preserving Actor-to-Object Graph Transformations. In David Hutchison, Takeo Kanade, Josef Kittler, Jon M. Kleinberg, Friedemann Mattern, John C. Mitchell, Moni Naor, Oscar Nierstrasz, C. Pandu Rangan, Bernhard Steffen, Madhu Sudan, Demetri Terzopoulos, Doug Tygar, Moshe Y. Vardi, Gerhard Weikum, Paolo Bellavista, Ruay-Shiung Chang, Han-Chieh Chao, Shin-Feng Lin, and Peter M. A. Sloot, editors, Advances in Grid and Pervasive Computing, volume 6104, pages 244–255. Springer Berlin Heidelberg, Berlin, Heidelberg, 2010. doi:10.1007/978-3-642-13067-0_28.
  • [30] Wei-Jen Wang and Carlos A. Varela. Distributed Garbage Collection for Mobile Actor Systems: The Pseudo Root Approach. In Yeh-Ching Chung and José E. Moreira, editors, Advances in Grid and Pervasive Computing, volume 3947, pages 360–372. Springer Berlin Heidelberg, Berlin, Heidelberg, 2006. doi:10.1007/11745693_36.
  • [31] Paul Watson and Ian Watson. An efficient garbage collection scheme for parallel computer architectures. In G. Goos, J. Hartmanis, D. Barstow, W. Brauer, P. Brinch Hansen, D. Gries, D. Luckham, C. Moler, A. Pnueli, G. Seegmüller, J. Stoer, N. Wirth, J. W. Bakker, A. J. Nijman, and P. C. Treleaven, editors, PARLE Parallel Architectures and Languages Europe, volume 259, pages 432–443. Springer Berlin Heidelberg, Berlin, Heidelberg, 1987. doi:10.1007/3-540-17945-3_25.

Appendix A Appendix

A.1 Basic Properties

Lemma A.1.

If BB has undelivered messages along x:AB{x:A\multimap B}, then xx is an unreleased refob.

Proof A.2.

There are three types of messages: 𝚊𝚙𝚙,𝚒𝚗𝚏𝚘,\mathtt{app},\mathtt{info}, and 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release}. All three messages can only be sent when xx is active. Moreover, the Release rule ensures that they must all be delivered before xx can be released.

Lemma A.3.

  

  • Once 𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(y:AC,z:BC)\mathtt{CreatedUsing}({y:A\multimap C},{z:B\multimap C}) is added to AA’s knowledge set, it will not be removed until after AA has sent an 𝚒𝚗𝚏𝚘\mathtt{info} message containing zz to CC.

  • Once 𝙲𝚛𝚎𝚊𝚝𝚎𝚍(z:BC)\mathtt{Created}({z:B\multimap C}) is added to CC’s knowledge set, it will not be removed until after CC has received the (unique) 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release} message along zz.

  • Once 𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(z:BC)\mathtt{Released}({z:B\multimap C}) is added to CC’s knowledge set, it will not be removed until after CC has received the (unique) 𝚒𝚗𝚏𝚘\mathtt{info} message containing zz.

Proof A.4.

Immediate from the transition rules.

Lemma A.5.

Consider a refob x:AB{x:A\multimap B}. Let t1,t2t_{1},t_{2} be times such that xx has not yet been deactivated at t1t_{1} and xx has not yet been released at t2t_{2}. In particular, t1t_{1} and t2t_{2} may be before the creation time of xx.

Suppose that αt1(A)𝚂𝚎𝚗𝚝(x,n)\alpha_{t_{1}}(A)\vdash\mathtt{Sent}(x,n) and αt2(B)𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍(x,m)\alpha_{t_{2}}(B)\vdash\mathtt{Received}(x,m) and, if t1<t2t_{1}<t_{2}, that AA does not send any messages along xx during the interval [t1,t2][t_{1},t_{2}] . Then the difference max(nm,0)\max(n-m,0) is the number of messages sent along xx before t1t_{1} that were not received before t2t_{2}.

Proof A.6.

Since xx is not deactivated at time t1t_{1} and unreleased at time t2t_{2}, the message counts were never reset by the SendRelease or Compaction rules. Hence nn is the number of messages AA sent along xx before t1t_{1} and mm is the number of messages BB received along xx before t2t_{2}. Hence max(nm,0)\max(n-m,0) is the number of messages sent before t1t_{1} and not received before t2t_{2}.

A.2 Chain Lemma

See 5.2

Proof A.7.

We prove that the invariant holds in the initial configuration and at all subsequent times by induction on events κ𝑒κ\kappa\xrightarrow{e}\kappa^{\prime}, omitting events that do not affect chains. Let κ=α|μχρ\kappa=\langle\!\langle\ \alpha\ |\ \mu\ \rangle\!\rangle^{\rho}_{\chi} and κ=α|μχρ\kappa^{\prime}=\langle\!\langle\ \alpha^{\prime}\ |\ \mu^{\prime}\ \rangle\!\rangle^{\rho^{\prime}}_{\chi^{\prime}}.

In the initial configuration, the only refob to an internal actor is y:AA{y:A\multimap A}. Since AA knows 𝙲𝚛𝚎𝚊𝚝𝚎𝚍(y:AA)\mathtt{Created}({y:A\multimap A}), the invariant is satisfied.

In the cases below, let x,y,z,A,B,Cx,y,z,A,B,C be free variables, not referencing the variables used in the statement of the lemma.

  • Spawn(x,A,B)\textsc{Spawn}(x,A,B) creates a new unreleased refob x:AB{x:A\multimap B}, which satisfies the invariant because α(B)𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x:AB)\alpha^{\prime}(B)\vdash\mathtt{Created}({x:A\multimap B}).

  • Send(x,y,z,A,B,C)\textsc{Send}(x,\vec{y},\vec{z},A,B,\vec{C}) creates a set of refobs RR. Let (z:BC)R({z:B\multimap C})\in R, created using y:AC{y:A\multimap C}.

    If CC is already in the root set, then the invariant is trivially preserved. Otherwise, there must be a chain (x1:A1C),,(xn:AnC)({x_{1}:A_{1}\multimap C}),\dots,({x_{n}:A_{n}\multimap C}) where xn=yx_{n}=y and An=AA_{n}=A. Then x1,,xn,zx_{1},\dots,x_{n},z is a chain in κ\kappa^{\prime}, since α(An)𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(xn,z)\alpha^{\prime}(A_{n})\vdash\mathtt{CreatedUsing}(x_{n},z).

    If BB is an internal actor, then this shows that every unreleased refob to CC has a chain in κ\kappa^{\prime}. Otherwise, CC is in the root set in κ\kappa^{\prime}. To see that the invariant still holds, notice that z:BC{z:B\multimap C} is a witness of the desired chain.

  • SendInfo(y,z,A,B,C)\textsc{SendInfo}(y,z,A,B,C) removes the 𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(y,z)\mathtt{CreatedUsing}(y,z) fact but also sends 𝚒𝚗𝚏𝚘(y,z,B)\mathtt{info}(y,z,B), so chains are unaffected.

  • Info(y,z,B,C)\textsc{Info}(y,z,B,C) delivers 𝚒𝚗𝚏𝚘(y,z,B)\mathtt{info}(y,z,B) to CC and adds 𝙲𝚛𝚎𝚊𝚝𝚎𝚍(z:BC)\mathtt{Created}({z:B\multimap C}) to its knowledge set.

    Suppose z:BC{z:B\multimap C} is part of a chain (x1:A1C),,(xn:AnC)({x_{1}:A_{1}\multimap C}),\dots,({x_{n}:A_{n}\multimap C}), i.e. xi=yx_{i}=y and xi+1=zx_{i+1}=z and Ai+1=BA_{i+1}=B for some i<ni<n. Since α(C)𝙲𝚛𝚎𝚊𝚝𝚎𝚍(xi+1:Ai+1C)\alpha^{\prime}(C)\vdash\mathtt{Created}({x_{i+1}:A_{i+1}\multimap C}), we still have a chain xi+1,,xnx_{i+1},\dots,x_{n} in κ\kappa^{\prime}.

  • Release(x,A,B)\textsc{Release}(x,A,B) releases the refob x:AB{x:A\multimap B}. Since external actors never release their refobs, both AA and BB must be internal actors.

    Suppose the released refob was part of a chain (x1:A1B),,(xn:AnB)({x_{1}:A_{1}\multimap B}),\dots,({x_{n}:A_{n}\multimap B}), i.e. xi=xx_{i}=x and Ai=AA_{i}=A for some i<ni<n. We will show that xi+1,,xnx_{i+1},\dots,x_{n} is a chain in κ\kappa^{\prime}.

    Before performing SendRelease(xi,Ai,B)\textsc{SendRelease}(x_{i},A_{i},B), AiA_{i} must have performed the Info(xi,xi+1,Ai+1,B)\textsc{Info}(x_{i},x_{i+1},\allowbreak A_{i+1},B) event. Since the 𝚒𝚗𝚏𝚘\mathtt{info} message was sent along xix_{i}, Lemma A.1 ensures that the message must have been delivered before the present Release event. Furthermore, since xi+1x_{i+1} is an unreleased refob in κ\kappa^{\prime}, Lemma A.3 ensures that α(B)𝙲𝚛𝚎𝚊𝚝𝚎𝚍(xi+1:Ai+1B)\alpha^{\prime}(B)\vdash\mathtt{Created}({x_{i+1}:A_{i+1}\multimap B}).

  • In(A,R)\textsc{In}(A,R) adds a message from an external actor to the internal actor AA. This event can only create new refobs that point to receptionists, so it preserves the invariant.

  • Out(x,B,R)\textsc{Out}(x,B,R) emits a message 𝚊𝚙𝚙(x,R)\mathtt{app}(x,R) to the external actor BB. Since all targets in RR are already in the root set, the invariant is preserved.

A.3 Termination Detection

Given a set of snapshots QQ taken before some time tft_{f}, we write QtQ_{t} to denote those snapshots in QQ that were taken before time t<tft<t_{f}. If ΦAQ\Phi_{A}\in Q, we denote the time of AA’s snapshot as tAt_{A}.

See 6.5 Call this set of snapshots QQ. First, we prove the following lemma.

Lemma A.8.

If Q𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x:AB)Q\vdash\mathtt{Unreleased}({x:A\multimap B}) and BQB\in Q, then xx is unreleased at tBt_{B}.

Proof A.9.

By definition, Q𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x:AB)Q\vdash\mathtt{Unreleased}({x:A\multimap B}) only if Q𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x)¬𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x)Q\vdash\mathtt{Created}(x)\land\lnot\mathtt{Released}(x). Since Q⊬𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x)Q\not\vdash\mathtt{Released}(x), we must also have ΦB⊬𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x)\Phi_{B}\not\vdash\mathtt{Released}(x). For Q𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x)Q\vdash\mathtt{Created}(x), there are two cases.

Case 1: ΦB𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x)\Phi_{B}\vdash\mathtt{Created}(x). Since ΦB⊬𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x)\Phi_{B}\not\vdash\mathtt{Released}(x), Lemma A.3 implies that xx is unreleased at time tBt_{B}.

Case 2: For some CQC\in Q and some yy, ΦC𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(y,x)\Phi_{C}\vdash\mathtt{CreatedUsing}(y,x). Since CC performed its final action before taking its snapshot, this implies that CC will never send the 𝚒𝚗𝚏𝚘\mathtt{info} message containing xx to BB.

Suppose then for a contradiction that xx is released at time tBt_{B}. Since ΦB⊬𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x)\Phi_{B}\not\vdash\mathtt{Released}(x), Lemma A.3 implies that BB received an 𝚒𝚗𝚏𝚘\mathtt{info} message containing xx before its snapshot. But this is impossible because CC never sends this message.

Proof A.10 (Proof (Lemma 6.5)).

By strong induction on time tt, we show that QQ is closed and that every actor appears blocked.

Induction hypothesis: For all times t<tt^{\prime}<t, if BQtB\in Q_{t^{\prime}} and Q𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x:AB)Q\vdash\mathtt{Unreleased}({x:A\multimap B}), then AQA\in Q, Q𝙰𝚌𝚝𝚒𝚟𝚎(x)Q\vdash\mathtt{Active}(x), and Q𝚂𝚎𝚗𝚝(x,n)Q\vdash\mathtt{Sent}(x,n) and Q𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍(x,n)Q\vdash\mathtt{Received}(x,n) for some nn.

Since Q0=Q_{0}=\emptyset, the induction hypothesis holds trivially in the initial configuration.

Now assume the induction hypothesis. Suppose that BQB\in Q takes its snapshot at time tt with Q𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x:AB)Q\vdash\mathtt{Unreleased}({x:A\multimap B}), which implies Q𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x)¬𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x)Q\vdash\mathtt{Created}(x)\land\lnot\mathtt{Released}(x).

Q𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x)Q\vdash\mathtt{Created}(x) implies that xx was created before tft_{f}. Lemma A.8 implies that xx is also unreleased at time tft_{f}, since BB cannot perform a Release event after its final action. Hence AA is in the closure of {B}\{B\} at time tft_{f}, so AQA\in Q.

Now suppose ΦA⊬𝙰𝚌𝚝𝚒𝚟𝚎(x)\Phi_{A}\not\vdash\mathtt{Active}(x). Then either xx will be activated after tAt_{A} or xx was deactivated before tAt_{A}. The former is impossible because AA would need to become unblocked to receive xx. Since xx is unreleased at time tft_{f} and tA<tft_{A}<t_{f}, the latter implies that there is an undelivered 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release} message for xx at time tft_{f}. But this is impossible as well, since BB is blocked at tft_{f}.

Finally, let nn such that ΦB𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍(x,n)\Phi_{B}\vdash\mathtt{Received}(x,n); we must show that ΦA𝚂𝚎𝚗𝚝(x,n)\Phi_{A}\vdash\mathtt{Sent}(x,n). By the above arguments, xx is active at time tAt_{A} and unreleased at time tBt_{B}. Since both actors performed their final action before their snapshots, all messages sent before tAt_{A} must have been delivered before tBt_{B}. By Lemma A.5, this implies ΦA𝚂𝚎𝚗𝚝(x,n)\Phi_{A}\vdash\mathtt{Sent}(x,n).

We now prove the safety theorem, which states that if QQ is a finalized set of snapshots, then the corresponding actors of QQ are terminated. We do this by showing that at each time tt, all actors in QtQ_{t} are blocked and all of their potential inverse acquaintances are in QQ.

Consider the first actor BB in QQ to take a snapshot. We show, using the Chain Lemma, that the closure of this actor is in QQ. Then, since all potential inverse acquaintances of BB take snapshots strictly after tBt_{B}, it is impossible for BB to have any undelivered messages without appearing unblocked.

For every subsequent actor BB to take a snapshot, we make a similar argument with an additional step: If BB has any potential inverse acquaintances in QtBQ_{t_{B}}, then they could not have sent BB a message without first becoming unblocked.

See 6.4

Proof A.11.

Proof by induction on events. The induction hypothesis consists of two clauses that must both be satisfied at all times ttft\leq t_{f}.

  • IH 1: If BQtB\in Q_{t} and x:AB{x:A\multimap B} is unreleased, then Q𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x)Q\vdash\mathtt{Unreleased}(x).

  • IH 2: The actors of QtQ_{t} are all blocked.

Initial configuration

Since Q0=Q_{0}=\emptyset, the invariant trivially holds.

Snapshot(B,ΦB)\textsc{Snapshot}(B,\Phi_{B})

Suppose BQB\in Q takes a snapshot at time tt. We show that if x:AB{x:A\multimap B} is unreleased at time tt, then Q𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x)Q\vdash\mathtt{Unreleased}(x) and there are no undelivered messages along xx from AA to BB. We do this with the help of two lemmas.

Lemma A.12.

If Q𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x:AB)Q\vdash\mathtt{Unreleased}({x:A\multimap B}), then xx is unreleased at time tt and there are no undelivered messages along xx at time tt. Moreover, if tA>tt_{A}>t, then there are no undelivered messages along xx throughout the interval [t,tA][t,t_{A}].

Proof A.13 (Proof (Lemma)).

Since QQ is closed, we have AQA\in Q and ΦA𝙰𝚌𝚝𝚒𝚟𝚎(x)\Phi_{A}\vdash\mathtt{Active}(x). Since BB appears blocked, we must have ΦA𝚂𝚎𝚗𝚝(x,n)\Phi_{A}\vdash\mathtt{Sent}(x,n) and ΦB𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍(x,n)\Phi_{B}\vdash\mathtt{Received}(x,n) for some nn.

Suppose tA>tt_{A}>t. Since ΦA𝙰𝚌𝚝𝚒𝚟𝚎(x)\Phi_{A}\vdash\mathtt{Active}(x), xx is not deactivated and not released at tAt_{A} or tt. Hence, by Lemma A.5, every message sent along xx before tAt_{A} was received before tt. Since message sends precede receipts, each of those messages was sent before tt. Hence there are no undelivered messages along xx throughout [t,tA][t,t_{A}].

Now suppose tA<tt_{A}<t. Since ΦA𝙰𝚌𝚝𝚒𝚟𝚎(x)\Phi_{A}\vdash\mathtt{Active}(x), xx is not deactivated and not released at tAt_{A}. By IH 2, AA was blocked throughout the interval [tA,t][t_{A},t], so it could not have sent a 𝚛𝚎𝚕𝚎𝚊𝚜𝚎\mathtt{release} message. Hence xx is not released at tt. By Lemma A.5, all messages sent along xx before tAt_{A} must have been delivered before tt. Hence, there are no undelivered messages along xx at time tt.

Lemma A.14.

Let x1:A1B,,xn:AnB{x_{1}:A_{1}\multimap B},\dots,{x_{n}:A_{n}\multimap B} be a chain to x:AB{x:A\multimap B} at time tt. Then Q𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x)Q\vdash\mathtt{Unreleased}(x).

Proof A.15 (Proof (Lemma)).

Since all refobs in a chain are unreleased, we know in,ΦB⊬𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(xi)\forall i\leq n,\ \Phi_{B}\not\vdash\mathtt{Released}(x_{i}) and so Q⊬𝚁𝚎𝚕𝚎𝚊𝚜𝚎𝚍(xi)Q\not\vdash\mathtt{Released}(x_{i}). It therefore suffices to prove, by induction on the length of the chain, that in,Q𝙲𝚛𝚎𝚊𝚝𝚎𝚍(xi)\forall i\leq n,\ Q\vdash\mathtt{Created}(x_{i}).

Base case: By the definition of a chain, αt(B)𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x1)\alpha_{t}(B)\vdash\mathtt{Created}(x_{1}), so 𝙲𝚛𝚎𝚊𝚝𝚎𝚍(x1)ΦB\mathtt{Created}(x_{1})\in\Phi_{B}.

Induction step: Assume Q𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(xi)Q\vdash\mathtt{Unreleased}(x_{i}), which implies AiQA_{i}\in Q. Let tit_{i} be the time of AiA_{i}’s snapshot.

By the definition of a chain, either the message [B𝚒𝚗𝚏𝚘(xi,xi+1)][B\triangleleft\mathtt{info}(x_{i},x_{i+1})] is in transit at time tt, or αt(Ai)𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(xi,xi+1)\alpha_{t}(A_{i})\vdash\mathtt{CreatedUsing}(x_{i},x_{i+1}). But the first case is impossible by Lemma A.12, so we only need to consider the latter.

Suppose ti>tt_{i}>t. Lemma A.12 implies that AiA_{i} cannot perform the SendInfo(xi,xi+1,Ai+1,B)\textsc{SendInfo}(x_{i},x_{i+1},A_{i+1},B) event during [t,ti][t,t_{i}]. Hence αti(Ai)𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(xi,xi+1)\alpha_{t_{i}}(A_{i})\vdash\mathtt{CreatedUsing}(x_{i},x_{i+1}), so Q𝙲𝚛𝚎𝚊𝚝𝚎𝚍(xi+1)Q\vdash\mathtt{Created}(x_{i+1}).

Now suppose ti<tt_{i}<t. By IH 2, AiA_{i} must have been blocked throughout the interval [ti,t][t_{i},t]. Hence AiA_{i} could not have created any refobs during this interval, so xi+1x_{i+1} must have been created before tit_{i}. This implies αti(Ai)𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(xi,xi+1)\alpha_{t_{i}}(A_{i})\vdash\mathtt{CreatedUsing}(x_{i},x_{i+1}) and therefore Q𝙲𝚛𝚎𝚊𝚝𝚎𝚍(xi+1)Q\vdash\mathtt{Created}(x_{i+1}).

Lemma A.14 implies that BB cannot be in the root set. If it were, then by the Chain Lemma there would be a refob y:CB{y:C\multimap B} with a chain where CC is an external actor. Since Q𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(y)Q\vdash\mathtt{Unreleased}(y), there would need to be a snapshot from CC in QQ – but external actors do not take snapshots, so this is impossible.

Since BB is not in the root set, there must be a chain to every unreleased refob x:AB{x:A\multimap B}. By Lemma A.14, Q𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x)Q\vdash\mathtt{Unreleased}(x). By Lemma A.12, there are no undelivered messages to BB along xx at time tt. Since BB can only have undelivered messages along unreleased refobs (Lemma A.1), the actor is indeed blocked.

Send(x,y,z,A,B,C)\textsc{Send}(x,\vec{y},\vec{z},A,B,\vec{C})

In order to maintain IH 2, we must show that if BQtB\in Q_{t} then this event cannot occur. So suppose BQtB\in Q_{t}. By IH 1, we must have Q𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(x:AB)Q\vdash\mathtt{Unreleased}({x:A\multimap B}), so AQA\in Q. By IH 2, we moreover have AQtA\not\in Q_{t} – otherwise AA would be blocked and unable to send this message. Since BB appears blocked in QQ, we must have ΦA𝚂𝚎𝚗𝚝(x,n)\Phi_{A}\vdash\mathtt{Sent}(x,n) and ΦB𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍(x,n)\Phi_{B}\vdash\mathtt{Received}(x,n) for some nn. Since xx is not deactivated at tAt_{A} and unreleased at tBt_{B}, Lemma A.5 implies that every message sent before tAt_{A} is received before tBt_{B}. Hence AA cannot send this message to BB because tA>t>tBt_{A}>t>t_{B}.

In order to maintain IH 1, suppose that one of the refobs sent to BB in this step is z:BC{z:B\multimap C}, where CQtC\in Q_{t}. Then in the next configuration, 𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(y,z)\mathtt{CreatedUsing}(y,z) occurs in AA’s knowledge set. By the same argument as above, AQQtA\in Q\setminus Q_{t} and ΦA𝚂𝚎𝚗𝚝(y,n)\Phi_{A}\vdash\mathtt{Sent}(y,n) and ΦC𝚁𝚎𝚌𝚎𝚒𝚟𝚎𝚍(y,n)\Phi_{C}\vdash\mathtt{Received}(y,n) for some nn. Hence AA cannot perform the SendInfo(y,z,A,B,C)\textsc{SendInfo}(y,z,A,B,C) event before tAt_{A}, so ΦA𝙲𝚛𝚎𝚊𝚝𝚎𝚍𝚄𝚜𝚒𝚗𝚐(y,z)\Phi_{A}\vdash\mathtt{CreatedUsing}(y,z) and Q𝙲𝚛𝚎𝚊𝚝𝚎𝚍(z)Q\vdash\mathtt{Created}(z).

SendInfo(y,z,A,B,C)

By the same argument as above, AQtA\not\in Q_{t} cannot send an 𝚒𝚗𝚏𝚘\mathtt{info} message to BQtB\in Q_{t} without violating message counts, so IH 2 is preserved.

SendRelease(x,A,B)\textsc{SendRelease}(x,A,B)

Suppose that AQtA\not\in Q_{t} and BQtB\in Q_{t}. By IH 1, x:AB{x:A\multimap B} is unreleased at time tt. Since QQ is finalized, ΦA𝙰𝚌𝚝𝚒𝚟𝚎(x)\Phi_{A}\vdash\mathtt{Active}(x). Hence AA cannot deactivate xx and IH 2 is preserved.

In(A,R)\textsc{In}(A,R)

Since every potential inverse acquaintance of an actor in QtQ_{t} is also in QQ, none of the actors in QtQ_{t} is a receptionist. Hence this rule does not affect the invariants.

Out(x,B,R)\textsc{Out}(x,B,R)

Suppose (y:BC)R({y:B\multimap C})\in R where CQtC\in Q_{t}. Then yy is unreleased and Q𝚄𝚗𝚛𝚎𝚕𝚎𝚊𝚜𝚎𝚍(y)Q\vdash\mathtt{Unreleased}(y) and BQB\in Q. But this is impossible because external actors do not take snapshots.