Actor State

YAActL follows Julia's philosophy in giving the user responsibility for access to internals and implementing correct programs:

You are entirely responsible for ensuring that your program is data-race free, and nothing promised here can be assumed if you do not observe that requirement. The observed results may be highly unintuitive. [1]

When using multi-threading we have to be careful when using functions that are not pure as we might get a wrong answer. [2]

Since concurrency is the overarching theme of actor programming, and behavior functions must access data to do their job, data-race freedom is a major concern in working with actors. As a ground rule actors don't share state and mutable variables.

Internal State

Actors have an internal mutable state variable:

YAActL._ACTType
_ACT()

Internal actor status variable.

Fields

  1. dsp::Dispatch: dispatch mode,
  2. sta::Tuple: the actor's status variable,
  3. res::Tuple: the result of the last behavior execution,
  4. bhv::Func : the behavior function and its internal arguments,
  5. init::Func: the init function and its arguments,
  6. term::Func: the terminate function and its arguments,
  7. self::Link: the actor's (local or remote) self,
  8. name::Symbol: the actor's registered name.

see also: Dispatch, Func, Link

source

Functions executed by an actor can access their actor's internal ACT variable via task_local_storage("ACT"). Normally this is not needed.

We must express two important concerns regarding actor state:

Actor state is multifaceted!

Actor state is not a single value but includes behavior functions, arguments and an explicit mutable state variable, which is used for state Dispatch or for representing agents.

Sharing state can cause critical race conditions!

You must be careful not to share any of the state variables between actors in order to avoid critical race conditions.

Create Private Actor State

The returned value of the init! function is saved as an actors state sta. It is a good practice to have an init function to create a private actor state with defined initial parameters.

Be careful to update! the actor's state since this overwrites it. Don't update it with a shared variable!

Update Actor State

Only the actor itself is allowed to update its state in a strictly sequential manner by processing message after message.

Other actors or users can cause an actor to update its state by sending it a message, which is done implicitly by using the API function update!.

Behavior Function Arguments

Julia functions accept mutable types as parameters and can change their values. YAActL messages and API functions allow to send mutable variables.

If your behavior functions get mutable types as parameters, you must ensure that

  • either you don't share those variables between actors
  • or you don't change them by using only pure functions as behaviors.

Mutable Variables

Sharing mutable variables is dangerous!

Race conditions can happen if actors in parallel use or modify global or shared variables. The best advice is not to use global or shared variables with actors.

If for some reason you want to use global variables or to share variables between actors, you must use a lock or atomic operations described in the Julia manual. But both approaches block an actor until it succeeds to access the variable.