Advanced Join Patterns for the Actor Model based on CEP Techniques
Humberto Rodriguez Avila, Joeri De Koster, Wolfgang De Meuter
AAdvanced Join Patterns for the Actor Model based on CEPTechniques
Humberto Rodriguez Avila a , Joeri De Koster a , and Wolfgang De Meuter a a Software Languages Lab, Vrije Universiteit Brussel, Belgium Abstract
Context
Actor-based programming languages offer many essential features for developing modern distributedreactive systems. These systems exploit the actor model’s isolation property to fulfill their performance andscalability demands. Unfortunately, the reliance of the model on isolation as its most fundamental propertyrequires programmers to express complex interaction patterns between their actors to be expressed manuallyin terms of complex combinations of messages sent between the isolated actors.
Inquiry
In the last three decades, several language design proposals have been introduced to reduce thecomplexity that emerges from describing said interaction and coordination of actors. We argue that noneof these proposals is satisfactory in order to express the many complex interaction patterns between actorsfound in modern reactive distributed systems.
Approach
We describe seven smart home automation scenarios (in which an actor represents every smarthome appliance) to motivate the support by actor languages for five fundamentally different types of messagesynchronization patterns, which are lacking in modern distributed actor-based languages. Fortunately, thesefive types of synchronisation patterns have been studied extensively by the Complex Event Processing (CEP)community. Our paper describes how such CEP patterns are elegantly added to an actor-based programminglanguage.
Knowledge
Based on our findings, we propose an extension of the single-message matching paradigm ofcontemporary actor-based languages in order to support a multiple-message matching way of thinking in thesame way as proposed by CEP languages. Our proposal thus enriches the actor-model by ways of declarativelydescribing complex message combinations to which an actor can respond.
Grounding
We base the problem-statement of the paper on an online poll in the home automation communitythat has motivated the real need for the CEP-based synchronisation operators between actors proposed in thepaper. Furthermore, we implemented a DSL — called Sparrow — that supports said operators and we arguequantitatively (in terms of LOC and in terms of a reduction of the concerns that have to be handled byprogrammers) that the DSL outperforms existing approaches.
Importance
This work aims to provide a set of synchronization operators that help actor-based languages tohandle the complex interaction required by modern reactive distributed systems. To the best of our knowledge,our proposal is the first one to add advanced CEP synchronization operators to the — relatively simplisticsingle-message based matching— mechanisms of most actor-based languages.
ACM CCS 2012Software and its engineering → Domain specific languages ; Concurrent programming languages ; Functional languages ; Keywords actors, coordination, complex event processing, join patterns, rete
The Art, Science, and Engineering of Programming
Submitted
June 2, 2020
Published
November 1, 2020 doi © Humberto Rodriguez Avila, Joeri De Koster, and Wolfgang De MeuterThis work is licensed under a “CC BY 4.0” license.In
The Art, Science, and Engineering of Programming , vol. 5, no. 3, 2020, article 10; 31 pages. dvanced Join Patterns for the Actor Model based on CEP Techniques
The actor model [25] is a well-established paradigm for developing distributed reactivesystems. The actor model’s concurrency properties are fundamental to achieve thekind of performance and scalability required by such systems in the face of havingto handle millions of simultaneous connections [10]. In the original actor model,interaction and coordination of actors are achieved entirely by cleverly encodedasynchronous message exchanges between those actors. Nevertheless, whenever anactor is supposed to execute a method in response to a received set of messages (ratherthan just a single message) with certain characteristics, mainstream actor languages(e.g., Erlang, Scala, Elixir) require developers to encode the characteristics of the setmanually. This is illustrated in listing 1 (lines 4, 7, 9). In this example, the actor willreact only if a particular sequence of messages (
M s gA → M s g B → M s g C ) is received.To delay the execution of the reaction code (line 11) until the expected messages havebeen received in the right order, the actor must manually keep track (lines 5, 8, 13)of previous messages, and validate the progress of subsequent message arrivals in ahard-coded fashion (line 10).Briefly, the single-message match mechanism of traditional actors complicates theconstruction of said distributed reactive systems. Developers are forced to manuallyweave and braid two orthogonal concerns of their actor’s interactions and coordina-tions: when to react (i.e., precisely describe the set of messages that is supposed togive rise to a certain behaviour) and how to react (i.e., the code that describes theactual method to be fired upon reception of said set).
Listing 1
Example of how to detect a sequence of messages in Elixir def loop({ts_a, ts_b}) do state = receive do {:msg_a, timestamp} -> {timestamp, ts_b} {:msg_b, timestamp} -> {ts_a, timestamp} {:msg_c, timestamp} -> if ts_b > ts_a do end {0,0} end loop(state) end For more than three decades, researchers have been developing new programminglanguage features to improve the expressiveness of the interaction and coordinationfeatures of actors. In section 5 we will present an extensive overview of the state-of-the-art in this domain. One notable technique is based on join patterns . This techniquewas popularised by Haller and Van Cutsem [23], where an extension of Scala ispresented featuring join patterns. Join patterns where invented by Benton, Cardelli, and Fournet [9] as part of the join calculus. They were added to the thread-basedconcurrency model of C
Get and
Put ) of a
Buffer class. In thisexample, the calling thread of the
Get method will be blocked until the asynchronous
Put method is invoked. The ampersand ( & ) symbol expresses declaratively that both threads need to rendezvous before the method’s body is executed. Listing 2
Expressiveness of a join pattern in Polyphonic C public class Buffer { public string Get() & public async
Put( string s) { return s; } } In this paper, we use seven smart home automations (in which every home applianceis represented by an actor) to motivate the necessity to easily encode very complexinteractions and coordinations between actors. Based on an extensive poll in thesmart home community on the internet, we show that these are seven real-worldconcerns that are on the radar of actual developers of such systems. From theseseven automations, we identify five different types of message synchronisation operators .Then, we show that the current state-of-the-art in actor coordination and interactiontechnologies in general, and join patterns in particular falls short in supporting theseoperators.Based on this problem statement, we present Sparrow, a dialect of Elixir thatfeatures actors whose complex interaction and coordination patterns can be describedin a highly declarative fashion. Sparrow’s interaction patterns (which support ouridentified synchronisation operators) have been harvested from our extensive literaturestudy of the state-of-the-art of Complex Event Processing (CEP). Hence, Sparrow canbe seen as an actor language whose actors have been enriched with CEP and joinpattern ideas. We use a smart home scenario as an application domain to help steerour research. However, we conjecture Sparrow as a general-purpose actor coordinationframework that can be used to express synchronisation patterns for other event-drivendomains (e.g., SmartCities[26], SmartBuildings[43]) as well.The main contributions of this paper are:We showcase current challenges for modern actor languages to coordinate largegroups of heterogeneous actors using seven smart home scenarios (see section 2).These use cases are not just synthetic scenarios but have been validated in thesmart home community. Elixir can be regarded as a modern Erlang (e.g., with macros) that runs atop BEAM; i.e.,the Erlang virtual machine.
We present a novel set of advanced actor synchronisation abstractions by formulat-ing them as a domain-specific Elixir extension, called Sparrow (see section 3).We validate our proposal by implementing the seven smart home scenarios todemonstrate the expressiveness of the resulting code (see section 4).We show the novelty of our approach by contrasting it with the state-of-the-art andrelated work on actor interaction and coordination techniques (see section 5).
One application domain where complex interactions between different participants ofa system occur is the smart home automation domain. In our scenario, each smartdevice is digitally represented by an actor (also called digital twin [2]). These digitaltwins can be run on the device itself or any other machine, for instance, on theedge (e.g., raspberry pi) or a cloud-based platform (e.g., SmartThings). The complexinteractions between the smart home devices then need to be encoded throughmessage passing between their respective digital twins. For complex scenarios, thiswill require advanced synchronisation patterns to express these different interactions.In this section, we present seven home automation scenarios that exemplify fivefundamental synchronisation operators required to coordinate a group of actors.These are: Turn on the lights in a room if someone enters, and the ambient light is less than 40lux. Turn off the lights in a room after two minutes without detecting any movement. Send a notification when a window has been open for over an hour. Send a notification if someone presses the doorbell, but only if no notification wasalready sent in the past 30 seconds. Detect home arrival or leaving based on a particular sequence of messages, and activatethe corresponding scene. Send a notification if the combined electricity consumption of the past three weeks isgreater than 200 kWh. Send a notification if the boiler fires three Floor Heating Failures and one InternalFailure within the past hour, but only if no notification was sent in the past hour.
The above examples were inspired by real automation rules shared on communityforums of smart home platforms (e.g., openHAB and Hass ). While conducting thisstudy, we only considered complex scenarios that cannot be expressed using a simplemobile app (e.g., Home App from Apple). Each of these complex scenarios was thenclassified and consolidated into the seven different scenarios described above. These The postman always rings twice. A scene is set of actions to be taken in a certain state of the home automation system. openHAB Forum ( https://community.openhab.org , last accessed 2020-10-01). Hass Forum ( https://community.home-assistant.io , last accessed 2020-10-01).
E1 E2 E3 E4 E5 E6 E7
Scenarios % o f v o t e s Figure 1
Results of the online poll. Total of voters: 714. Voting time: 1 month consolidated scenarios highlight different complex coordination patterns between agroup of smart devices, which can be abstracted into five primary synchronizationoperators described at the end of this section. To validate that each of our scenarios isa representative example of the different synchronisation patterns found in the wild,we published an online poll. Each respondent was required to reply with a yes-or-noanswer whether or not they had to implement synchronisation patterns similar toeach of our seven scenarios.Our poll was published in four smart home community forums (openHAB [7],Hass [5], SmartThings [8], and Hubitat [6]) for one month and, during that time,collected 714 votes. Figure 1 shows the results of this poll. Due to our poll’s non-probabilistic nature, we cannot derive any statistical certainties based on its results.However, it does show that our scenarios are good examples of concerns that presentthemselves within that community. For example, scenario 1 exemplifies the needfor synchronizing multiple independent messages. In this scenario, there are twosensors (motion and light) whose messages need to be synchronized. This concern wasidentified and raised as a known issue by 662 (92.72 %) of the voters. Scenarios 2, 3, 4,and 5 rely on fairly advanced time-based synchronisation of messages. Furthermore,scenario 5 requires to enforce a particular order in which its constituent messagesmust match. Our poll shows that timing-constraints and message-order are also twowell-recognized concerns within the home automation community. Even the complexscenarios (6 and 7) that require aggregation of multiple messages of the same typeover a certain time window were still encountered by more than a quarter of therespondents. The results of our poll do not validate our list of scenarios as exhaustive. However, itdoes give us the certainty that the listed scenarios represent common synchronisationpatterns found in the wild. Despite these results, we found that both current thread-based smart home platforms and actor languages lack synchronisation abstractionsto coordinate heterogeneous smart home devices. We base this statement on ourexperience after implementing all our examples in two popular smart home platforms Possibly because scenarios (6, 7) target expensive devices which currently offer limitedintegration with third-party platforms. (openHAB and Hass) and a modern actor language (Elixir). These selected pro-gramming environments offer at least the same synchronisation abstractions as theirstate-of-the-art alternatives (e.g., SmartThings, Akka/Scala). The full implementationof each of the seven scenarios using each of the three programming environmentscan be found online [4]. Each of our implementations using both openHab and Hasswas presented and improved based on feedback from their respective communities.Listing 3 shows the degree of complexity that users of current smart home platformshave to handle by themselves to implement scenario 5. Our openHAB solution consid-ers two motion sensors, one in the entrance hall ( α ), and the second one outside thefront door ( δ ). Furthermore, we use a contact sensor ( β ) to detect when the frontdoor was opened. The occupied-home scene is enabled by the following sequence ofmessages δ → β → α , and the empty-home scene by α → β → δ . Both scenes will beactivated if the three messages occur in a time window of 60 seconds. This imple-mentation also assumes that only one person lives in the smart home. Although oursolution was improved thanks to the feedback received from the openHAB community,it exposes a lack of programming abstractions to synchronize messages from multipledevices. First, we are responsible for keeping track of each sensor’s last update ( β line 9, α line 15, δ line 28). Second, we manually discard messages older than the 60seconds time window (lines 17, 30). Finally, we have to verify that the messages werereceived in the right order (lines 20, 33) before executing the automation’s reaction.In summary, our openHAB solution and its Elixir alternative required more than 20lines of essential code to express the coordination of only three devices.Further study of each of the scenarios allowed us to disambiguate five categories ofoperators that are required to express each of the synchronisation patterns. Filter operators are required to enable the filtering of messages based on their attributevalues or timing constraints. For example, in scenario 1, we are required to filterout messages from the ambient light sensor for which the value does not reach 40lux. Scenario 4 and 6 show the need for filtering messages based on the absence orpresence of messages within a certain time window respectively.
Selection operators are required to select messages from the set of matching messagesafter filtering. Traditional actor languages only allow for the consumption of theoldest (first in) message. However, we will require more flexible message selectionpolicies. For example, in scenario 7, we are only interested in the latest
InternalFailure message, and the third
Floor Heating Failure message. In general, expressingthese types of constraints will require selection operators that allow us to selectany message from the set of matching messages after filtering.
Correlation operators are required to match a set of different types of messages andto unify their attributes. For example, in scenario 1, we are required to match amotion sensor message and an ambient light sensor message but only match if bothare present. Additionally, in scenario 5, we are also required to specify the order inwhich those messages arrived in order to trigger the right scene. Depending onthe order in which sensors detected movement, the person either left the house orarrived home.
Listing 3
Jython-script implementation for scenario 5 in openHAB c_door = ZDT.now().minusHours(24) m_hall = ZDT.now().minusHours(24) m_door = ZDT.now().minusHours(24) @rule ("(Py) Front Door Opened") @when ("Item Front_Door_Contact changed to OPEN") def front_door_opened(e): global c_door c_door = ZDT.now() @rule ("(Py) Motion Detected - Entrance Hall") @when ("Item Entrance_Hall_Motion changed to ON") def entrance_hall_motion(e): global m_hall, m_door, c_door m_hall = ZDT.now() if m_door.isBefore(m_hall.minusSeconds(60)): return if m_hall.isAfter(c_door) and c_door.isAfter(m_door): @rule ("(Py) Motion Detected - Front Door") @when ("Item Front_Door_Motion changed to ON") def front_door_motion(e): global m_hall, m_door, c_door m_door = ZDT.now() if m_hall.isBefore(m_door.minusSeconds(60)): return if m_door.isAfter(c_door) and c_door.isAfter(m_hall): Accumulation operators are required to aggregate a set of matching messages afterfiltering. For example, in scenario 6, we are required to aggregate electricityconsumption messages of the last three weeks into their sum.
Transformation operators are required to transform (e.g., map) a list of accumulatedmessages. These messages can be subject to new predicate conditions. For example,in scenario 6, we need to check if the total electricity consumption is greater than200 kWh before sending a notification. Only if the predicate condition is true allthe accumulated messages are consumed.In this section, we have identified the above five types of operators that are requiredto express complex synchronisation patterns. Unfortunately, as we show in moredetail in section 5, state-of-the-art actor languages and frameworks lack the necessarysupport for these types of operators. Contrary, the above operators are frequentlysupported by CEP languages/frameworks (e.g., TESLA [11], ETALIS [3], PARTE [37],FlinkCEP [47], and Esper [27]). In the next section, we explore the integration of thewell understood CEP operators into actors to overcome these limitations.
In this section, we introduce the main contribution of this paper, to wit a novel joinpattern language called Sparrow. Like previous join pattern languages [23, 32, 33],Sparrow extends the traditional single-message match interface of actors [25] tosupport multiple-message match. However, in order to support the five synchroni-sation operators described in the previous section, Sparrow’s join pattern languagedesign is heavily inspired by CEP languages and frameworks. Sparrow leveragesthe macro facilities of the Elixir programming language for its implementation. Assuch, Sparrow is implemented as a domain-specific language (DSL) that benefits fromthe integration of the extensive set of Elixir/Erlang libraries in that ecosystem. Theconceptual model underlying Sparrow’s technical implementation was formalisedinto an executable operational semantics using PLT-Redex [14]. The description ofthis operational semantics can be found in a companion technical report [40] for thispaper.Listing 4 shows an implementation of scenarios 1 and 2 in Sparrow. A Sparrowmodule (Actor definition) consists of four parts: importing Sparrow’s macros (line 2),pattern definitions (lines 4–-14), reaction definitions (lines 16, 17), reaction bindings(lines 19, 20).The Sparrow programming language can be subdivided into two smaller languages.On the one hand, there is the
Sparrow’s pattern language (see section 3.1); thisis a declarative subset of Sparrow (inspired by CEP languages) that enables thedeclaration of complex synchronisation patterns (see listing 4, lines 4–-14). On theother hand, the
Sparrow’s reaction language (see section 3.2) is a superset of theElixir programming language in which the reaction to a matching pattern can bespecified (see listing 4, lines 16, 17). The react_to with: special form ties both languagestogether. It determines which reactions will be fired after a complex synchronisation
Listing 4
Main parts of a Sparrow program defmodule SparrowByExample do use Sparrow.Actor pattern motion as {:motion, id, status, room} pattern light as {:light, id, status, room} pattern on_motion as motion{status= :on} and light{status= :on} and {:amb_light, id, value, room} when value > 40, options: [last: true] pattern no_motion as not motion{status= :on}[ window: {2, :mins}] and light{status= :on}, options: [last: true] reaction turn_on_light(l, i, t), do: reaction turn_off_light(l, i, t), do: react_to on_motion, with: turn_on_light react_to no_motion, with: turn_off_light end
EBNF-styled grammar for the Sparrow’s pattern language pattern has been detected. The next subsections describe both parts of the Sparrowlanguage in detail and their underlying implementation (see section 3.3). Figure 2shows an EBNF-styled grammar for the Sparrow’s pattern language. The definitionfor
Elementary patterns are the most basic kind of patterns. They always start with a selector that designates a single message followed by an optional operator and anoptional guard expression. Defining a new pattern in Sparrow can be done usingthe pattern special form. Figure 3 shows the definition of an elementary patternthat matches when an open window is detected at any location (this is part ofthe implementation for scenario 3). The pattern keyword is used to give a name tothe pattern. In Sparrow, patterns are second-class citizens that can be reused andcomposed to define complex patterns. The as keyword is followed by the selector ofthe pattern. Similar to Elixir’s messages, a selector in Sparrow is represented as atuple. Its first element determines the type of message to match, and always hasa unique constant value ( :window in our example). The other selector elements arecalled attributes, and they can be primitive values (e.g., String, Number) or logicvariables . Logic variables represent a dynamic primitive value that is unknown untilthe matching of the pattern against a message that sits in the actor’s inbox. pattern open_window as {:window, id, :open, location}
21 3
Figure 3
Example of an elementary pattern: (1) Primitive to declare a pattern; (2) Assigna name for future references; (3) Define the pattern’s selector
As with plain Elixir/Erlang, pattern matching on primitive values can be used tofilter messages based on their attribute values. For instance, the pattern shown in ourexample will only match :window messages for which the second attribute ( status ) hasas value :open . The other attributes ( id, location ) are logic variables.
Operators are high-level conditions that further delineate the kind of messages thatcan be matched by the pattern selector. A selector can optionally be followed by oneor more operators enclosed in square brackets. Elementary patterns support three The type of a selector is always an Elixir atom ( : ). types of operators: negation , debouncing , and extensional sequencing . For example,figure 4 shows an implementation for scenario 2 that uses a negation operator. Forthis scenario, we want to turn off the lights after two minutes without movement.Detecting the absence of motion events can be implemented in Sparrow by using thenegation operator ( not ) in combination with a timing window. pattern turn_off_light as not {:motion, id, :on, location}[window: {2, :mins}] Figure 4
Implementation of scenario 2 using a negated pattern: (1) Negate the selectordefinition; (2) Set the time window
Negated selectors must always be combined with a time window (e.g., in seconds,minutes, or hours). Every time the selector matches a new message, the time windowis reset. Once the time window expires, the pattern is automatically matched.Figure 5 shows an implementation of scenario 4 using the debouncing operator.For this scenario, we only want to match doorbell messages if no other doorbellmessage was matched in the past 30 seconds. A debounced operator does exactlythat, the first message that matches the preceding selector automatically matchesthe entire pattern. Any future messages that follow within the debouncing time areautomatically discarded. pattern doorbell_alert as {:doorbell, id}[debounce: {30, :secs}] Figure 5
Implementation of scenario 4 using a debouncing time between messages
Finally, figure 6 presents the use of the extensional sequencing operator in order toimplement a partial solution for scenario 7. For our partial solution, we are interestedin matching every third heating failure event. This can be done in Sparrow by followingthe pattern selector with an extensional sequencing operator using the every keyword.In our example, only every third message is matched and consumed. All other messagesthat match the selector are discarded. pattern heating_failure as {:heating_f, id, code}[every: 3] Figure 6
Example using the extensional sequencing operator ( every ) of Sparrow
Guards are boolean predicates that are executed after a match of the selector andits operators is found. Like with traditional Elixir guards [48], Sparrow guards areonly allowed to contain boolean predicate expressions that can always be executed The integration of Sparrow in Elixir required us to design negation as a prefix operator, anddebouncing and sequencing as postfix operators. The term debouncing is taken from the domain of electrical circuits where a particulardebouncing algorithm is used to avoid multiple triggers (within a period) to produce anundesired control output [19]. in constant time (and are side-effect free). Figure 7 shows a guarded pattern thatwill be activated if it matches an open window message from the bedroom or thekitchen. The full pattern is only matched (and the corresponding reaction fired) whenthe guard expression evaluates to true . If the guard expression evaluates to false , thepattern is not matched, and the messages are not consumed. pattern open_window as {:window, id, :open, location} when location == :bedroom or location == :kitchen Figure 7
Example of a pattern with a guard expression
Elementary patterns that have been named by means of the pattern keyword can bereused, further specified or composed with other patterns.
Reusing elementary patterns can be done by specifying a pattern name instead ofa selector when defining a new pattern. An optional set of inline guards can followthis name. Inline guards are just syntactic sugar to write compact guard expressions.Pattern reuse is illustrated in figure 8, which shows two semantically equivalentvariants (B, C) of a pattern that extends another elementary pattern (A). Both patternsare matched whenever a window of the kitchen is open. Pattern B uses a guardexpression to further specify that the open window needs to be detected in thekitchen using the equals operator ( == ). On the other hand, pattern C employs an inlineguard to substitutes the logic variable location for the atom :kitchen using the matchoperator ( = ). pattern open_window as {:window, id, :open, location} pattern kitchen_window_a as open_window when location == :kitchen pattern kitchen_window_b as open_window{location= :kitchen} ABC
Figure 8
Examples of pattern reuse: (A) Definition of an elementary pattern; (B) Furtherspecifying an existing pattern with an additional guard expression; (C) Definitionof a reused pattern with an additional inline guard
Composing patterns can be done by linking multiple elementary patterns by meansof a logic operator. Sparrow supports both conjunctions ( and ) and disjunctions ( or )of patterns. Figure 9 illustrates the use of composing patterns in order to partiallyimplement smart home scenario 5. For this scenario, we are interested in detectingwhen the user is arriving home by first detecting motion at the front door, followed byreceiving an open door event, followed by detecting motion in the entrance hall. In our Like with traditional actor languages; disjunction can also be achieved by separating each ofthe patterns in the disjunction. However, as Sparrow also has conjunction, which is usuallynot supported by traditional actor languages, we also syntactically support disjunction. example, the occupied_home pattern is defined as a conjunction of three elementarypatterns. The first and third one reuse the motion_sensor pattern to match only motionevents from the front door and entrance hall respectively, On the other hand, thesecond one is an anonymous pattern that matches door opening events.Any composed pattern can be followed by an optional set of operators. By default,a composed pattern does not enforce any particular order in which its constituents’patterns must match. However, that behaviour can be changed using the intensionalsequencing operator ( seq ). In our example of figure 9, we set sequencing to true inorder to specify that the occupied_home pattern can only be matched if the matchedmessages arrive in the same order as they are specified in the pattern definition. pattern occupied_home as motion_sensor{location= :front_door} and {:contact, id, :open, :front_door} and motion_sensor{location= :entrance_hall}, options: [ seq: true ] pattern motion_sensor as {:motion, id, :on, location} Figure 9
Example of use of sequencing operator ( seq ) Renaming logic variables
Sparrow has support for unification of logical variablescrossing the constituents of a composed pattern. This is often desirable as it allowsfor the unification of various attributes across different pattern selectors. However,Sparrow currently unhygienically expands all named patterns into the composedpattern (similar to unhygienic macros). This can potentially lead to unexpectedunification of logical variables when composing named patterns. For example, ourfirst implementation of scenario 5 in figure 9 contains a bug as it incorrectly doesnot match the sequence of messages shown in figure 10.A. Figure 10.B shows theexpanded form of the composite pattern defined in figure 9. Each of the selectorsof the elementary patterns contains the same logical variable id . However, in thiscase, it is undesirable to unify these three logical variables as each sensor can have adifferent id. To circumvent this issue, Sparrow allows developers to manually changethe logical variable for an attribute using the aliasing operator ( ~> ). The aliasingoperator renames the logical variable on its left-hand side to the logical variableon its right-hand side in the elementary pattern. This operator is not an optimalsolution. In future versions of Sparrow, the default behaviour of unification will bechanged to facilitate the maintenance of large pattern sets. However, as patterns arenot first-class entities, developers can identify shared logic variables by looking atthe pattern definition. Figure 10.C presents an improved version of the occupied_home pattern. Timing constraints on composite patterns
Similar to windowing for elementary pat-terns, composite patterns also support timing-constraints. Developers can specify a time-interval in which the composed set of patterns should be matched. Figure 11presents a new version of the occupied_home pattern where the 60 seconds time con-straint is added. Similar to intentional sequencing, this time constraint ( interval ) isalso defined in the options of a composite pattern. {:motion, 30, :on, :front_door} {:contact, 20, :open, :front_door} {:motion, 31, :on, :entrance_hall} t t t Time
AB 1 {:motion, id, :on, :front_door} and {:contact, id, :open, :front_door} and {:motion, id, :on, :entrance_hall} C pattern occupied_home as motion_sensor{location= :front_door} and {:contact, cid, :open, :front_door} and motion_sensor{location= :entrance_hall,id~> mid}, options: [ seq: true ] Figure 10
Example of a composite pattern with shared logic variables: (A) Sample of mes-sages; (B) Expansion of the occupied_home pattern’s composite selector; (B.1)Highlight shared logic variables; (C) Fixed declaration of the occupied_home pattern; (C.1) Change attribute identifier; (C.2) Rename attribute identifier usingthe alias operator pattern occupied_home as motion_sensor{location= :front_door} and {:contact, cid, :open, :front_door} and motion_sensor{location= :entrance_hall,id~> mid}, options: [ seq: true, interval: {60, :secs} ] Figure 11
Example of a composite pattern with a time interval constraint
Composite patterns selection strategy
Like most actor languages, Sparrow messagesare matched in FIFO order. However, Sparrow enables one to deviate from that defaultselection strategy. Figure 6 already showed an example of this by only selecting everythird message. This particular message selection strategy is useful to synchronizealways on the latest messages that may be relevant to a pattern. For example, theimplementation of the pattern occupied_home from figure 11 must always check allpotential messages received from the three sensors in the last 60 seconds. However,as observed in figure 12.A at t , the pattern should only check the latest message ( t )from the entrance hall’s motion sensor and discard the old ones ( t , t ). AB pattern occupied_home as motion_sensor{location= :front_door} and {:contact, id, :open, :front_door} and motion_sensor{location= :entrance_hall, id ~> mid}, options: [ seq: true, interval: {60, :secs},last: true ] t Time t t t t M_FrontDoorC_FrontDoorM_EntHall
Figure 12
A solution to the occupied-home scene of scenario 5: (A) Messages received bythe actor; (B) Composite pattern that enforces a selection strategy ( last-in ) Accumulation patterns extend elementary patterns with quantified and unquantifiedaccumulation of sets of the same type of message. Once the set of messages is accumu-lated, further transformation and filtering can be applied. Accumulation patterns canbe constructed from elementary patterns by means of several optional accumulation operators. Like other operators (see section 3.1.1), they can be specified betweensquare brackets following the selector.
Quantified accumulation patterns are used to accumulate a fixed number of matchingmessages. Figure 13.A shows a pattern that uses the count operator to match threeheating failure messages. However, similar to reused patterns, the pattern expansionstep of Sparrow’s macros will unhygienically expand these patterns. In our example,this means that the pattern heating_failure accumulates three heating failure messagesfrom the same boiler and with the same failure code as the logical variables id and code will be unified (see figure 13.B). Although this default behaviour may be usefulin some circumstances, it is not always desirable.Sparrow introduces the operators: must be distinct ! and may be distinct @ , to specifythe expected matching behaviour of logic variables when used in an accumulationpattern. The former guarantees that the constrained attribute must have a distinct value in all the messages accumulated. In contrast, the latter allows the constrainedattribute to have any value. For example, the definition of heating_failure pattern shownin figure 13.C will match three messages from the same boiler regardless of the code attribute’s value. pattern heating_failure as {:heating_f, id, code}[count: 3] AB {:heating_f, id, code} and {:heating_f, id, code} and {:heating_f, id, code} pattern heating_failure as {:heating_f, id, @code}[count: 3] C Figure 13
Example of a quantified accumulation pattern that matches three heating failuremessages: (A) Use of the operator count to accumulate tree messages; (B)Highlight shared logic variables in expanded pattern; (C) Use of the may bedistinct operator @ to accumulate messages regardless of the code attribute’svalue Unquantified accumulation patterns are used to accumulate any number of messageswithin a certain time window using the window operator. Figure 14.A shows a patternthat uses the window operator to accumulates all heating failure messages from thelast 60 minutes. Messages older than the time constraint are automatically removedby Sparrow’s run-time. As a second example of unquantified accumulation patterns,figure 14.B shows a hybrid accumulation pattern that use both count and time-based accumulation operators. In this last case, the first operator that reaches its conditionwill win and result in a match.
Transformation operators allow developers to transform and filter a group of receivedmessages that have been accumulated. For example, figure 15.B presents a pattern thatimplements the requirements for scenario 6. Notice that the electricity_alert patternuses the may be distinct operator (B.1) to match all daily consumption values. Oncethe accumulation operator is satisfied (B.2), the list of messages is transformed (B.3).Later, the pattern uses the special form bind (B.4) to save total electricity consumption pattern heating_failure as {:heating_f, id, @code}[window: {60, :mins}] A pattern heating_failure as {:heating_f, id, @code}[count: 3, window: {60, :mins}] B Figure 14
Examples of unquantified accumulation patterns: (A) Use of the window operatorto accumulate all messages in the last 60 minutes; (B) Example mixing bothaccumulation operators in a local variable ( total ). Finally, the guard expression (B.5) is evaluated to determineif the messages are consumed or not by the pattern. In this example, messages olderthan three weeks are automatically discarded by the Sparrow runtime. pattern daily_electricity as {:consumption, meter_id, value} pattern electricity_alert as daily_electricity{@value}[window: {3, :weeks}] |> fold(0, fn({_,_,v}, acc)-> acc + v end) |> bind(total) when total > 200 B 2 345
Figure 15
Sparrow solution for scenario 6: (A) Elementary pattern definition; (B) Accumu-lation pattern example with a transformer operator and guard
So far, we have only focused on the Sparrow’s pattern language. However, once apattern is matched, the matched messages are consumed, i.e., removed from theactor’s inbox, and the actor starts reacting to the matched pattern. In Sparrow, thisreaction logic is syntactically decoupled from the pattern definition (similar to [51]).A reaction can be dynamically bound to one or more patterns, and a pattern can havemultiple reactions. This behaviour was intentionally designed to facilitate the reuse ofboth patterns and reactions. Furthermore, it avoids developers to add an extra layerof indirection (middleman) to determine which reactions to execute. The middlemanapproach circumvents the duplicity definition of both patterns and reactions. However,it also introduces a performance penalty since it is always notified whether a patternhas registered reactions or not. In summary, the decoupling of patterns and reactionsallows the programmer to dynamically change the behaviour of a Sparrow actor, whichis reminiscent of a become statement in the original actor model.Figure 16 showcases a smart home scenario where the binding of reactions to apattern is based on the current season of the year (e.g., summer, winter). In thisway, developers can avoid duplicated patterns with different reactions to match theseason requirements. This figure omits the code related to the dynamic schedulingof the reactions. Figure 16.A shows the definition of two reactions ( turn_off_heating , turn_off_cooling ) using the reaction special form. Both reactions can be bound to thepattern window_open (see figure 16.B) based on the current season. The definition ofa reaction is similar to the definition of a named function that always has the same reaction turn_off_heating (mgs, int_res, state), do: react_to open_window, with: turn_off_heating remove turn_off_cooling, from: open_window remove_reactions open_window reaction turn_off_cooling (mgs, int_res, state), do: B pattern open_window as {:window, id, :open, location} Figure 16
Overview of reaction primitives: (A) Define two reactions; (B) Add a reaction toa pattern; (C) Remove a reaction from a pattern; (D) Remove all reaction of apattern three parameters. The first one (A.1) is a list of messages matched by the pattern.The second parameter (A.2) is a key-value list with all the intermediate results savedwith the bind operator during a transformation process (see figure 15.B.4). Finally, thethird parameter (A.3) represents the current state of the actor. In this example, thedefinition of both reactions omits the code related to their body and their dynamicscheduling.Binding a reaction to a pattern is done using the react_to special form (see figure 16.C)which expects two arguments: the pattern’s name (C.1), and the reaction’s name (C.2).When the pattern open_window (see figure 16.B) is successfully matched, the actor willinvoke all its reactions in the same order they were bound to the pattern. A reactioncan also be unbound from a pattern. The remove primitive function (see figure 16.D)also expects the same two arguments as the react_to primitive function but in reverseorder. Finally, the remove_reactions function (see figure 16.E) removes all the reactionsof the pattern received as argument.
As mentioned in section 3, Sparrow extends the traditional single-message matchinterface of actors to support multiple-message match. To achieve that, a Sparrowactor has a virtual-inbox that it is used as a knowledge base of an embedded patternengine . Like the traditional actor’s inbox, the virtual-inbox is theoretically unboundedin size. However, unlike traditional actor languages, Sparrow messages have a finitelifetime. Each actor can define a default lifetime for the messages it receives. After amessage expires, it is automatically garbage collected by the pattern engine.The pattern engine builds a directed graph (also known as discrimination network)representing all patterns defined in its actor. Internally, Sparrow’s patterns are rep-resented by a special type of node called pattern node . These nodes implement thedifferent synchronisations operators motivated in section 2 and supported by Sparrow.Additionally, each pattern node maintains a history (called buffer ) of previous matchedmessages. Although in figure 17 patterns are represented by a single type of node,
Pattern Engine
Actor
Inbox DiscriminationNetwork
Reaction Executor Pattern’s reactions MessageMessage being transferedRoot node Pattern node Reaction in execution LegendVirtual-Inbox
Figure 17
Overview of the internal representation of a Sparrow actor: (1) Transfer ofa received message to the virtual-inbox; (2) Feed the engine’s discriminationnetwork with a new message; (3) Queue pattern reaction after a successfulmatch several subtypes exist, each of them addressing a particular type of pattern defined insection 3.Figure 17 shows a simplified view of the internal representation of an actor inSparrow and its message matching process. The matching process starts by transferringeach received message from the actor’s inbox into the virtual-inbox . Later the patternengine tries to match each new message against a group of patterns for which it isrelevant; we call this process a match-cycle . The discrimination network’s root node serves as the entry point of new messages for the matching process. This node willdetermine potential pattern nodes based on the message’s type and will forward it tothem. After this step, the message will flow through the discrimination network untila pattern node with a successful match of its conditions is found. In that case, themessage is consumed by its reaction(s), which will be one after the other executedsequentially by the actor’s reaction executor . Otherwise, the message remains in thenode’s buffer until a successful match is completed or until the message expires. Theabove process is an essential tool for the engine’s incremental matching strategy. Thisstrategy is based on a custom implementation of the RETE algorithm [15]. Furthermore,it implements a single pattern selection and selected message consumption policies [54].The former guarantees that a pattern matches at most once per match-cycle. Thelatter guarantees that a pattern can consume a message only once. However, multiplepatterns can consume the same message. The details of this implementation can befound in our GitHub repository. https://github.com/softwarelanguageslab/sparrow In this section, we evaluate Sparrow’s expressiveness by comparing its solutions toour seven scenarios against the ones expressed in two popular smart home platforms(openHab, Hass) and one actor language (Elixir). We chose Elixir because it is thehost language of our DSL, and it provides synchronisation abstractions similar toother mainstream actor languages (e.g., Erlang, Scala). We followed a quantitativeevaluation approach based on an analysis of the lines of code required to express eachautomation’s coordination logic. In other words, our comparison does not considercode not related to the coordination process (e.g., imports, reaction logic of theautomations). To obtain a fair comparison between our actor-based solutions andthe ones from the smart home platforms, we published these solutions on bothcommunity’s forums (see openHAB [39] and Hass [38] topics). This allowed us to getfeedback, and incrementally arrive at a solution that could be implemented by expertsin these communities in our comparison. Figure 18 shows a solution to scenario 5in openHAB (A), Elixir (B), and Sparrow (C). We decided to analyse this particularsolution since it showcases most of the actions that developers have to take careof during the implementation of our scenarios. Due to the similarity between thesolutions of openHAB (Jython) and Hass (Python), we omitted the latter. However,the interested reader can inspect this and the rest of our solutions in our GitHubrepository [4].As can be observed in figure 18, for this particular automation, the Sparrow’s solutionis the most compact of all three. However, we want to compare the relative amount ofcode that we (as developers) have to write for handling all different concerns relatedto the synchronisation of messages. To do this analysis, we highlighted four concernsthat we frequently found in the implementations of our smart home scenarios. Thefirst one ( state management ) indicates the code that is used to save temporal datarequired by the ongoing coordination process. For example, in both openHAB andElixir implementations, we had to manually track each sensor’s most recent message,spending 42.86 % and 40 % respectively of the coordination code on that action.However, Sparrow shields developers from this kind of work. The second concern( windowing management ) highlights the code needed to discard messages that do notsatisfy the pattern’s timing constraints. In contrast, the third one ( sequencing control )points the code to enforce a particular message order. The coordination code requiredfor these two actions in automation 5 was relatively simple. However, unlike Sparrow(lines 10, 13), the complexity of these synchronisation operations in openHAB (lines 21,24, 33, 36) and Elixir (lines 8, 9, 16, 17) is directly proportional to the number of devicesinvolved. The last concern, pattern definition emphasizes the code used to express thetype of messages to be synchronized and their content-based conditions. Although it isthe most crucial concern for the coordination process, openHAB and Elixir’s patternsonly define when to react to single messages. The inability to express the wholecoordination process by means of declarative patterns forces developers to shift theirfocus from when to react to how to do it. By contrast, in Sparrow (see figure 18.C), adeveloper focuses on the declaration of patterns, and he lets the run-time to figureout how to match its constituents.
Sequencing control
Windowing managementPattern definitionState management C defmodule Automation5 do use Sparrow.Actor 3 4 pattern motion as {:motion, id, :on, location} 5 pattern m_front_door as motion{location= :front_door} 6 pattern m_entrance_hall as motion{location= :entrance_hall, id~> mid} 7 pattern c_front_door as {:contact, cid, :open, :front_door} 8 9 pattern occupied_home as m_front_door and c_front_door and m_entrance_hall,10 options: [ interval: {60, :secs}, seq: true, last: true ]11 12 pattern empty_home as m_entrance_hall and c_front_door and m_front_door,13 options: [ interval: {60, :secs}, seq: true, last: true ]14 15 reaction activate_home_scene(l, i, t), do: reaction activate_leave_scene(l, i, t), do: react_to occupied_home, with: activate_home_scene19 react_to empty_home, with: activate_leave_scene20 21 end B defmodule Automation5 do import Timex 3 4 def loop({m_door, m_hall, c_door}) do
5 state = 6 receive do
7 {:motion, _id, :on, :front_door, m_door_dt} -> 8 if before?(shift(m_door_dt, seconds: -60), m_hall) do 9 if after?(m_door_dt, c_door) and after?(c_door, m_hall) do
10 end end
13 {m_door_dt, m_hall, c_door}1415 {:motion, _id, :on, :entrance_hall, m_hall_dt} ->16 if before?(shift(m_hall_dt, seconds: -60), m_door) do if after?(m_hall_dt, c_door) and after?(c_door, m_door) do
18 end end
21 {m_door, m_hall_dt, c_door}2223 {:contact, _id, :open, :front_door, dt} ->24 {m_door, m_hall, dt}25 end end
29 30 end A from core.rules import rule 2 from core.triggers import when 3 from java.time import ZonedDateTime as ZDT 4 5 c_door = ZDT.now().minusHours(24) 6 m_hall = ZDT.now().minusHours(24) 7 m_door = ZDT.now().minusHours(24) 8 9 @rule ("(Py) Front Door Opened")10 @when ("Item Front_Door_Contact changed to OPEN")11 def front_door_opened(event):12 global c_door13 c_door = ZDT.now()1415 @rule ("(Py) Motion Detected - Entrance Hall")16 @when ("Item Entrance_Hall_Motion changed to ON")17 def entrance_hall_motion(event):18 global m_hall, m_door, c_door19 m_hall = ZDT.now()20 21 if m_door.isBefore(m_hall.minusSeconds(60)):22 return
23 24 if m_hall.isAfter(c_door) and c_door.isAfter(m_door):25 @rule ("(Py) Motion Detected - Front Door")28 @when ("Item Front_Door_Motion changed to ON")29 def front_door_motion(event):30 global m_hall, m_door, c_door31 m_door = ZDT.now()3233 if m_hall.isBefore(m_door.minusSeconds(60)):34 return
35 36 if m_door.isAfter(c_door) and c_door.isAfter(m_hall):37 Figure 18
Solution for scenario 5 in openHAB (A), Elixir (B), and Sparrow (C) openHAB Hass Elixir SparrowState management 29 30 55 0Sequencing control 2 2 2 2Windowing management 20 15 12 7Pattern definition 24 13 31 16Total lines of code (LoC) 75 60 100 25 openHAB Hass Elixir Sparrow r e l a t i v e % o f L o C Figure 19
Summary of analyzing different solutions for the seven scenarios
Figure 19 summarizes our solutions with a breakdown of the total lines of code (LoC)and their respective relative percentage according to the four identified concerns. Foreach concern and platform/language, we show the sum of all LoC written in our sevensolutions. A detailed breakdown for each solution can be found in appendix A. Topopulate the values shown in this figure, we manually tagged each LoC related to thefour concerns. Later, we retrieve their sum values using a helper script ( statistics.exs )located in the root directory of each solution group (e.g., openHAB, Sparrow). Usingthis comparison, we show that Sparrow seems to succeed at reducing the effectsof non-functional concerns that arise during the synchronisation of messages in acomplex actor system.
Our main goal in this paper was to retrofit CEP operators onto the actor model toimprove the expressiveness of encoding the interaction and coordination of actorsthrough join patterns. In this section, we discuss how the related work done in thisdomain relates to the synchronisation operators described in section 2. We group thebelow proposals in three main categories: communication model extension , monitor &verification , and local synchronisation . Due to the not mutually exclusive definitionof our categories, some proposals may fit in more than one. Table 2 in appendix Bsummarizes the support for the five types of synchronisation operators by state-of-the-art actor frameworks and languages. Communication model extension
Most of the related work in this category add sup-port for a multi-cast message communication [1, 12, 20, 21, 22, 45]. Other relatedwork adds an extra synchronisation layer to the traditional actor’s point-to-pointcommunication model [28, 52]. Within this category we can further disambiguate be-tween approaches that synchronize messages on the sender-side and approaches thatsynchronize messages on the receiver-side. Sparrow falls within the latter category.All of these approaches filter messages based on their values and do not have supportfor time-based filtering of messages. Moreover, with the exception of interActors [21]and AErlang [12], all of the synchronisation mechanisms in this category are only10:
Most of the related work in this category add sup-port for a multi-cast message communication [1, 12, 20, 21, 22, 45]. Other relatedwork adds an extra synchronisation layer to the traditional actor’s point-to-pointcommunication model [28, 52]. Within this category we can further disambiguate be-tween approaches that synchronize messages on the sender-side and approaches thatsynchronize messages on the receiver-side. Sparrow falls within the latter category.All of these approaches filter messages based on their values and do not have supportfor time-based filtering of messages. Moreover, with the exception of interActors [21]and AErlang [12], all of the synchronisation mechanisms in this category are only10: able to match individual messages. In interActors, the sender of a message can waitfor two or more reply messages before continuing. On the other hand, AErlang hassupport for receiver-side synchronisation by allowing the receiver actor to accumulateand filter a finite number of messages of the same type. Our proposal takes this fur-ther by allowing the interface of an actor to synchronize different types of messages.Furthermore, our patterns extend the single message transformation of [28] to a listof messages. Contrary to Sparrow, none of the proposals in this category provideabstractions to detect the absence of messages, or enforce a matching order, or enablematching a disjunction of messages using a single pattern.
Monitor & verification
Related work in this category [13, 16, 17, 24, 29, 30, 31, 35,36, 44, 46] uses reflection to observe and limit the interaction of one or a groupof actors. The coordination process is mostly done by a special type of meta-actorswhich enforces a particular protocol for incoming and outgoing messages. In contrast,our proposal is based on a local synchronization of messages in the receiver actor.Like Sparrow, synchronization abstractions of the above proposals can filter messagesbased on their values and time constraints (e.g., [29, 35, 46]). However, the abstrac-tions provided by [24, 31] only supports type-based constraints. Furthermore, only[35] can detect the absence of messages, but it assumes that actors have their localclocks synchronized, and their invocations are scheduled atomically. Additionally, liketraditional actors, the synchronisation abstractions of these proposals always matchthe oldest messages. Contrary to Sparrow, message correlation operators are usedonly to enforce a particular communication protocol. The message receiver behaveslike a traditional actor matching a single message.
Local synchronisation
Proposals in this category can be further classified into twomain groups. The first one targets synchronisation approaches based on promises/-futures or message-passing continuations [18, 34, 49, 50, 53]. Unlike Sparrow, theirabstractions allow the synchronisation and chaining of individual message invocations.The second group extends the actor interface to match a set of messages instead of indi-vidual ones. Sparrow, like the other proposals in this category [23, 32, 33] expands thematching capabilities of the traditional actor’s receive primitive with join patterns [9].Join pattern languages commonly only support the unification of individual messages,except Activators [18] and Sparrow, where patterns can define disjunctions. However,Activators’ patterns cannot mix conjunctions and disjunctions of messages in a singlepattern like in Sparrow. Furthermore, unlike Sparrow, joins in none of these languagesenforce a particular matching order of their constituents’ messages. Languages inthis group use pattern-matching techniques to compact filtering expressions. Despitethat, only JErlang [33], JCThorn [32], and Sparrow support a non-linear patternmatching mechanism. This mechanism allows join patterns to synchronize the valuesof shared attributes among multiple messages without guard expressions. The abovejoin languages also force developers to statically bound patterns and reactions duringthe definition of a pattern. Furthermore, they lack support for timing constraints andaccumulation operators to filter messages.
Complicated message exchange patterns play an important role in the developmentof modern actor-based applications. We introduce five novel types of synchronisationoperators to describe coordination between actors in a modern actor-based language.The operators were inspired by well-established abstractions in the CEP domain. Theneed for the operators was supported by real-world scenarios coming from the smarthome automation community. A poll ran in the said community had endorsed ourproposal with fairly large evidence. Even the most exotic operator was on the wish listof no less than 25 percent of the developers. Our proposal has been realised technicallyin the form of an Elixir dialect called Sparrow. It was validated by implementing thescenarios in Sparrow, in two popular smart home automation platforms (openHab,Hass) and in raw Elixir. By labeling each line of code with the concern it contributesto, we have demonstrated that Sparrow does what it claims to do, namely givingactor programmers the abstractions necessary to declaratively specify complex inter-action patterns between actors. Sparrow’s join patterns have been implemented usingdiscrimination networks and a variant of the RETE algorithm in order to supportperformance. At the time of writing, we are benchmarking Sparrow against otheractor-based coordination approaches. New versions of our DSL will also mitigate theundesired unification of pattern attributes due to the current unhygienic expansionapproach. We are also working on an integration of Sparrow into the Hass smarthome platform. Furthermore, we plan to open-source Sparrow to the Elixir/Erlangcommunity, allowing us to harvest more user feedback from both communities.
Acknowledgements
We are thankful to the anonymous reviewers of Programmingfor their comments on an earlier version of this paper.
References [1] Gul Agha and Christian J. Callsen. “ActorSpace: An Open Distributed Program-ming Paradigm”. In:
Proceedings of the Fourth ACM SIGPLAN Symposium onPrinciples and Practice of Parallel Programming . PPOPP ’93. San Diego, California,USA: ACM, 1993, pages 23–32. isbn: 0-89791-589-5. doi: .[2] Kazi Masudul Alam and Abdulmotaleb El Saddik. “C2PS: A Digital Twin Ar-chitecture Reference Model for the Cloud-Based Cyber-Physical Systems”. In:
IEEE Access .[3] Darko Anicic, Paul Fodor, Sebastian Rudolph, Roland Stühmer, Nenad Sto-janovic, and Rudi Studer. “ETALIS: Rule-Based Reasoning in Event Process-ing”. In:
Reasoning in Event-Based Distributed Systems . Edited by Sven Helmer,Alexandra Poulovassilis, and Fatos Xhafa. Berlin, Heidelberg: Springer BerlinHeidelberg, 2011, pages 99–124. isbn: 978-3-642-19724-6. doi: . [4] Humberto Rodriguez Avila. Advanced Join Patterns for the Actor Model basedon CEP Techniques (Scenarios solutions) . Zenodo. Software. Aug. 3, 2019. doi: .[5] Humberto Rodriguez Avila.
Home Assistant - Automation Scenarios Poll . Zenodo.Aug. 2019. doi: .[6] Humberto Rodriguez Avila.
Hubitat - Automation Scenarios Poll . Zenodo. Aug.2019. doi: .[7] Humberto Rodriguez Avila.
OpenHAB - Automation Scenarios Poll . Zenodo. Aug.2019. doi: .[8] Humberto Rodriguez Avila.
SmartThings - Automation Scenarios Poll . Zenodo.Aug. 2019. doi: .[9] Nick Benton, Luca Cardelli, and Cédric Fournet. “Modern Concurrency Ab-stractions for C
ECOOP 2002 - Object-Oriented Programming . Edited byBoris Magnusson. Volume 2374. Lecture Notes in Computer Science. SpringerBerlin Heidelberg, 2002, pages 415–440. isbn: 3-540-43759-2. doi: .[10] Francesco Cesarini.
Which companies are using Erlang, and why? . Zenodo. Sept. 18, 2019. doi: .[11] Gianpaolo Cugola and Alessandro Margara. “TESLA: A Formally Defined EventSpecification Language”. In:
Proceedings of the Fourth ACM International Confer-ence on Distributed Event-Based Systems . DEBS ’10. Cambridge, United Kingdom:Association for Computing Machinery, 2010, pages 50–61. isbn: 978-1-60558-927-5. doi: .[12] Rocco De Nicola, Tan Duong, Omar Inverso, and Catia Trubiani. “AErlang: Em-powering Erlang with attribute-based communication”. In:
Science of ComputerProgramming
168 (2018), pages 71–93. issn: 0167-6423. doi: .[13] Peter Dinges and Gul Agha. “Scoped Synchronization Constraints for LargeScale Actor Systems”. In:
Coordination Models and Languages . Edited by MarjanSirjani. Lecture Notes in Computer Science. Berlin, Heidelberg: Springer BerlinHeidelberg, 2012, pages 89–103. isbn: 978-3-642-30829-1. doi: .[14] Matthias Felleisen, Robert Bruce Findler, and Matthew Flatt.
Semantics Engi-neering with PLT Redex . 1st edition. The MIT Press, 2009. isbn: 0-262-06275-5.[15] Charles L. Forgy. “Rete: A fast algorithm for the many pattern/many objectpattern match problem”. In:
Artificial Intelligence .[16] Simon Fowler. “An Erlang Implementation of Multiparty Session Actors”. In:
Proceedings 9th Interaction and Concurrency Experience, ICE 2016, Heraklion,Greece, 8-9 June 2016 . Edited by Massimo Bartoletti, Ludovic Henrio, SophiaKnight, and Hugo Torres Vieira. Volume 223. EPTCS. 2016, pages 36–50. doi: . [17] Svend Frølund and Gul Agha. “A Language Framework for Multi-Object Coor-dination”. In: ECOOP’ 93 — Object-Oriented Programming . Edited by Oscar M.Nierstrasz. Berlin, Heidelberg: Springer Berlin Heidelberg, 1993, pages 346–360. isbn: 978-3-540-47910-9. doi: .[18] Svend Frølund and Gul Agha. “Abstracting interactions based on messagesets”. In:
Object-Based Models and Languages for Concurrent Systems . Edited byPaolo Ciancarini, Oscar Nierstrasz, and Akinori Yonezawa. Berlin, Heidelberg:Springer Berlin Heidelberg, 1995, pages 107–124. isbn: 978-3-540-49269-6. doi: .[19] Jack G. Ganssle.
A Guide to Debouncing . Version 4. Apr. 2014. url: (visited on 2020-10-01).[20] Tony Garnock-Jones and Matthias Felleisen. “Coordinated Concurrent Pro-gramming in Syndicate”. In:
Programming Languages and Systems . Editedby Peter Thiemann. Lecture Notes in Computer Science. Berlin, Heidelberg:Springer Berlin Heidelberg, 2016, pages 310–336. isbn: 978-3-662-49498-1. doi: .[21] Hongxing Geng and Nadeem Jamali. “interActors: A Model for Separating Com-munication Concerns of Concurrent Systems”. In:
Programming with Actors:State-of-the-Art and Research Perspectives . Edited by Alessandro Ricci and PhilippHaller. Lecture Notes in Computer Science. Cham: Springer International Pub-lishing, 2018, pages 186–215. isbn: 978-3-030-00302-9. doi: .[22] Sebastian Gutierrez-Nolasco and Nalini Venkatasubramanian. “A ReflectiveMiddleware Framework for Communication in Dynamic Environments”. In:
On the Move to Meaningful Internet Systems 2002: CoopIS, DOA, and ODBASE .Edited by Robert Meersman and Zahir Tari. Lecture Notes in Computer Science.Berlin, Heidelberg: Springer Berlin Heidelberg, 2002, pages 791–808. isbn:978-3-540-36124-4. doi: .[23] Philipp Haller and Tom Van Cutsem. “Implementing Joins Using ExtensiblePattern Matching”. In:
Coordination Models and Languages . Berlin, Heidelberg:Springer Berlin Heidelberg, June 2008, pages 135–152. isbn: 978-3-540-68265-3.doi: .[24] Joseph Harrison. “Runtime Type Safety for Erlang/Otp Behaviours”. In:
Pro-ceedings of the 18th ACM SIGPLAN International Workshop on Erlang . Erlang2019. Berlin, Germany: Association for Computing Machinery, 2019, pages 36–47. isbn: 978-1-4503-6810-0. doi: .[25] Carl Hewitt, Peter Bishop, and Richard Steiger. “A Universal Modular ACTORFormalism for Artificial Intelligence”. In:
IJCAI’73: Proceedings of the 3rd In-ternational Joint Conference on Artificial Intelligence . IJCAI’73. Stanford, USA:Morgan Kaufmann Publishers Inc., 1973, pages 235–245.[26] IMEC.
City of Things . Zenodo. doi: . [27] EsperTech Inc. Esper documentation . url: (visited on 2020-10-26).[28] Ramtin Khosravi and Hamideh Sabouri. “Using Coordinated Actors to ModelFamilies of Distributed Systems”. In:
Coordination Models and Languages . Editedby Marjan Sirjani. Lecture Notes in Computer Science. Berlin, Heidelberg:Springer Berlin Heidelberg, 2012, pages 74–88. isbn: 978-3-642-30829-1. doi: .[29] Boualem Laichi and Yamina Sami. “ATC: actors with temporal constraints”. In:
Fourth IEEE International Symposium on Object-Oriented Real-Time DistributedComputing. ISORC 2001 . IEEE Computer Society, 2001, pages 306–313. doi: .[30] Naftaly H. Minsky and Victoria Ungureanu. “Regulated coordination in opendistributed systems”. In:
Coordination Languages and Models . Edited by DavidGarlan and Daniel Le Métayer. Volume 1282. Lecture Notes in Computer Science.Berlin, Heidelberg: Springer Berlin Heidelberg, 1997, pages 81–97. isbn: 978-3-540-69527-1. doi: .[31] Rumyana Neykova and Nobuko Yoshida. “Multiparty Session Actors”. In:
Coordi-nation Models and Languages . Edited by Eva Kühn and Rosario Pugliese. LectureNotes in Computer Science. Berlin, Heidelberg: Springer Berlin Heidelberg,2014, pages 131–146. isbn: 978-3-662-43376-8. doi: .[32] Ignacio Solla Paula. “JCThorn - Extending Thorn with joins and chords”. Mas-ter’s thesis. Department of Computing Imperial College London: Imperial Col-lege London, June 2010. url: (visited on 2020-10-26).[33] Hubert Plociniczak and Susan Eisenbach. “JErlang: Erlang with Joins”. In:
Coordination Models and Languages: 12th International Conference, COORDINA-TION 2010, Amsterdam, The Netherlands, June 7-9, 2010. Proceedings . Editedby Dave Clarke and Gul Agha. Berlin, Heidelberg: Springer Berlin Heidelberg,2010, pages 61–75. isbn: 978-3-642-13414-2. doi: .[34] Aleksandar Prokopec and Martin Odersky. “Isolates, Channels, and EventStreams for Composable Distributed Programming”. In:
Onward! 2015. Pittsburgh, PA, USA: Association forComputing Machinery, 2015, pages 171–182. isbn: 978-1-4503-3688-8. doi: .[35] Shangping Ren, Gul A. Agha, and Masahiko Saito. “A Modular Approachto Programming Distributed Real-Time Systems”. In:
Journal of Parallel andDistributed Computing . [36] Shangping Ren, Yue Yu, Nianen Chen, Kevin Marth, Pierre-Etienne Poirot, andLimin Shen. “Actors, Roles and Coordinators — A Coordination Model for OpenDistributed and Embedded Systems”. In: Coordination Models and Languages .Edited by Paolo Ciancarini and Herbert Wiklicky. Lecture Notes in ComputerScience. Berlin, Heidelberg: Springer Berlin Heidelberg, 2006, pages 247–265.isbn: 978-3-540-34695-1. doi: .[37] Thierry Renaux. “A Distributed Logic Reactive Programming Model and itsApplication to Monitoring Security”. PhD thesis. 2019. url: http://soft.vub.ac.be/Publications/2019/vub-soft-phd-19-01.pdf (visited on 2020-10-26).[38] Humberto Rodriguez Avila.
Hass Topics . Zenodo. July 2019. doi: .[39] Humberto Rodriguez Avila. openHAB Topics . Zenodo. July 2019. doi: .[40] Humberto Rodriguez Avila, Joeri De Koster, and Wolfgang De Meuter. “Ad-vanced Join-Patterns - A Technical Report”. Unpublished. url: https://soft.vub.ac.be/~hrguez/papers/tr-advanced-join-patterns.pdf .[41] Alceste Scalas and Nobuko Yoshida. “Lightweight session programming inscala”. In: . Edited by Benjamin S. Lerner and Shriram Krishnamurthi. Volume 56.30th European Conference on Object-Oriented Programming (ECOOP 2016).Schloss Dagstuhl–Leibniz-Zentrum fuer Informatik, 2016, 21:1–21:28. doi: .[42] Alceste Scalas, Nobuko Yoshida, and Elias Benussi. “Effpi: Verified Message-Passing Programs in Dotty”. In:
Proceedings of the Tenth ACM SIGPLAN Sympo-sium on Scala . Scala ’19. London, United Kingdom: Association for ComputingMachinery, 2019, pages 27–31. isbn: 978-1-4503-6824-7. doi: .[43] Schindler.
IoT Benefits of Schindler Ahead on Elevators & Escalators . Zenodo.Feb. 8, 2020. doi: .[44] Christophe Scholliers. “Ambient Contracts”. PhD thesis. 2013. url: https://soft.vub.ac.be/Publications/2013/vub-soft-phd-13-03.pdf (visited on 2020-10-26).[45] Christophe Scholliers, Elisa Gonzalez Boix, and Wolfgang De Meuter. “TOTAM:Scoped Tuples for the Ambient”. In:
Electronic Communications of the EASST .[46] Miao Song and Shangping Ren. “Coordination Operators and Their Composi-tion under the Actor-Role-Coordinator (ARC) Model”. In:
SIGBED Review .[47] Apache Flink Core Team.
FlinkCEP - Complex event processing for Flink . Sept. 15,2020. url: https://ci.apache.org/projects/flink/flink-docs-stable/dev/libs/cep.html (visited on 2020-10-26).[48] Elixir Core Team.
Guards - Official Documentation . Zenodo. Apr. 3, 2020. doi: . [49] Scala Core Team. Scala homepage . url: (visited on2020-10-26).[50] Tom Van Cutsem, Elisa Gonzalez Boix, Christophe Scholliers, Andoni LombideCarreton, Dries Harnie, Kevin Pinte, and Wolfgang De Meuter. “AmbientTalk:programming responsive mobile peer-to-peer applications with actors”. In:
Computer Languages, Systems & Structures .[51] Jurgen M. Van Ham, Guido Salvaneschi, Mira Mezini, and Jacques Noyé.“JEScala: Modular Coordination with Declarative Events and Joins”. In:
Pro-ceedings of the 13th International Conference on Modularity . MODULARITY ’14.Lugano, Switzerland: Association for Computing Machinery, 2014, pages 205–216. isbn: 978-1-4503-2772-5. doi: .[52] Carlos Varela and Gul Agha. “A Hierarchical Model for Coordination of Con-current Activities”. In:
Coordination Languages and Models . Edited by PaoloCiancarini and Alexander L. Wolf. Volume 1594. Lecture Notes in ComputerScience. Berlin, Heidelberg: Springer Berlin Heidelberg, 1999, pages 166–182.isbn: 978-3-540-48919-1. doi: .[53] Carlos Varela and Gul Agha. “Programming Dynamically Reconfigurable OpenSystems with SALSA”. In:
SIGPLAN Notices .[54] Detlef Zimmer and Rainer Unland. “On the Semantics of Complex Events inActive Database Management Systems”. In:
Proceedings of the 15th InternationalConference on Data Engineering . ICDE ’99. Washington, DC, USA: IEEE ComputerSociety, 1999, pages 392–399. isbn: 0-7695-0071-4. doi: . A LoC Breakdown of the Smart-Home Scenario Solutions
Table 1
Overview of lines of code for the different scenarios according to the four identifiedconcerns openHAB Hass Elixir SparrowState managementAutomation 1 0 3 7 0Automation 2 4 2 10 0Automation 3 1 2 6 0Automation 4 3 2 5 0Automation 5 9 10 6 0Automation 6 1 1 10 0Automation 7 11 10 11 0Sequencing controlAutomation 1 0 0 0 0Automation 2 0 0 0 0Automation 3 0 0 0 0Automation 4 0 0 0 0Automation 5 2 2 2 2Automation 6 0 0 0 0Automation 7 0 0 0 0Windowing managementAutomation 1 0 0 0 0Automation 2 6 4 4 1Automation 3 6 1 2 1Automation 4 1 1 1 1Automation 5 4 6 2 2Automation 6 1 1 0 1Automation 7 2 2 3 1Pattern definitionAutomation 1 3 2 5 2Automation 2 2 1 6 1Automation 3 4 1 4 1Automation 4 2 1 2 1Automation 5 6 3 4 6Automation 6 3 2 6 4Automation 7 4 3 4 1Total lines of code (LoC) 75 60 100 25
B Support of Synchronisation Operators by State-of-the-Art Proposals
Table 2
Overview of the synchronization operators addressed in state-of-the-art proposalsrelated to Sparrow
Filter Op. Selection Op. Correlation Op. Accum. Op. Transf. Op. C o n t e n t - b a s e d T i m e - b a s e d F l e x i b l e C o n j u n c t i o n D i s j u n c t i o n S e q u e n c i n g C o u n t - b a s e d T i m e - b a s e d A gg r e g a t i o n Communication model extensionsActorSpace[1] x - - - - - - - -TOTAM[45] x - - - - - - - -Directors[52] x - - - - - - - -Syndicate[20] x - - - - - - - -AErlang[12] x - - x a - - - - -interActors[21] x - - x a - - - - -RCF[22] x - - - - - - - -Coordinators[28] x - - - - - - - xMonitor & VerificationSynchronizers[17] x - - x x - - - -RTSynchronizers[35] x x - x x x - - -Scoped-Synchronizers[13] x - - x x - - - -Moses[30] x - - - - - - - -ATC[29] x x - - x - - - -ARC[36, 46] x x - - - x - - -Ambient Contracts[44] x - - x a - x - - -MPSA[31] x b - - - - - - - -MPSA-Erlang[16] x - - - - - - - -lchanels[41] x c - - - - - - - -Effpi[42] x c - - - - x d - - -OTyPe[24] x b - - - - - - - -Local synchronisationActivators[18] x - - x a x - - - -Salsa[53] x - - x a - - - - -Reactive Isolates[34] x - - x a - - - - xAmbientTalk[50] x - - x a - - - - -Scala/Akka[49] x - - x a - - - - -Scala Joins[23] x - - x - - - - -JErlang[33] x - - x - - - - -Sparrow x x x x x x x x x a Conjunction is only enforced to invocation of messages b Additional type-based constraints are applied to message’s attributes (e.g., MsgA(int, string)) c Type constraints to outgoing messages (object-level) are checked during the compilation phase d Sequencing is only enforced to outgoing messages
About the authors
Humberto Rodriguez Avila is a PhD student at the SoftwareLanguages Lab, Vrije Universiteit Brussel in Belgium. His mainresearch area is coordination of heterogeneous actors, and moreconcretely the design and implementation of programming tech-niques to express complex actor’s interaction patterns. Contacthim at [email protected] . Joeri De Koster is an assistant professor in programming lan-guages and runtimes. His current research is mainly focused onthe design, formalisation and implementation of parallel and dis-tributed programming languages. Contact him at [email protected] . Wolfgang De Meuter is a professor in programming languagesand programming tools. His current research is mainly situated inthe field of distributed programming, concurrent programming, re-active programming and big data processing. His research method-ology varies from more theoretical approaches (e.g., type systems)to building practical frameworks and tools (e.g., crowd-sourcingsystems). Contact him at [email protected] .10: