An Actor which looks after other Actors's

Every Actor is assigned a minder which it can call upong to provide general services (e.g. logging). The minder is also notified when an Actor dies or decides to Leave!. Therefor the minder can take action to replace a failed actor.



The star of the show (but not really)

This holds internal state for an Actor, it wraps the user defined state value. We usually think of the Actor as being the state value rather than this structure which is mostely hidden. It is rare that a user will need to access this directly. Usually Actors are referenced by an Id and we get the actor's details by calling accessor functions on either the Id or the Scene.

If you do access this, then you need to be careful to avoid concurrency violations.

Type Parameters

  • S The type of the user defined actor state.
  • M The message types the actor accepts, usually Any.

It is rare to set M, but if it is set then it should include at least Leave!.


Create an Actor with the given state and minder


Informs that an asynchronous Task failed


  • async::Task

    What failed


Informs that an Actor died


  • who::Id

    The Actor who died

  • corpse::Actors.Actor

    The Actor who died's data


The Address of an Actor

This is a safe reference to an Actor. It is most commonly used to send messages to an Actor. However many accessor methods take an Addr to safely get or set some Actor's internals or associated data.


This will grow in size as remote actors are added.

Type Parameters

  • S The type of the actor state.
  • M The message types the actor accepts, usually Any.

Request an actor be created with the given state. This is usually sent to an actor's minder which uses enter! to create the new actor.

It is expected that minders (subtypes of AbsMinder) implement this unless they are only intended for use with a special set of actors.


An Actor which prints messages to an IO stream

By default one of these is created which writes to stdout exlusively.


The context of message processing

Contains common information which is used by many different methods during message handling. You should assume that the members of this struct are likely to change.

Type Parameters

  • S The type of the current Actor's state. This is commonly specified when adding a method for hear (amongst much else).

  • M The message types accepted by the current Actor, usually Any.


The Root Actor

This contains the addresses for all the actors and bootstraps the play. Currently all actors are created by sending messages to the Stage although this will probably change in the future.

Any messages which the Stage can not handle, it forwards to the play.

The Stage bootstraps itself by putting the PreGenesis! message in its inbox. It processes this message first then sends Genesis! to the actor specified by play!.

It is unusual for the user to access this directly or override its behaviour. Most things can be achieved by creating a new AbsMinder type or allowing messages to be forwarded to the Play actor.


  • actors::Actors.AddressBook

    All the Actors in the play

  • time_to_leave::Union{Nothing, Timer}

    Grace period timer before force leaving

  • play::Id

    User defined play Actor


A temporary Actor which performs one action then leaves

Used by delegate


  • action::Function

    What the Stooge should do

  • args::Tuple

    The arguments passed to action


Organises actors into a hieracy or tree structure. This is used as the default AbsMinder for the play.

When an actor with this minder uses invite! the returned actor will be a child of the current actor (the current actor being the parent). An actor may have many children, but only a single parent.

  • If a child actor dies then the parent recieves Died!. By default actors don't know how to handle this so they will also die. (In any case the death will be logged).

  • If a parent leaves or dies, then its children are also asked to Leave!.

If you don't wish for an actor to die when one of its children do, then define hear for the Died! message.


  • root::Id

  • minded::Union{Nothing, Id}

  • children::Set{Id}


A group of Actor's

Messages shouted at the Troupe will be broadcast to the all the Actor's in it. To send a message to the Troupe itself, just use say.


Where a1..a3 are Actor Id's

g = enter!(s, Troupe(a1, a2, a3))
shout(s, g, Leave!())
say(s, g, Leave!())


  • as::Array{Id,1}

    The addresses of the Actors in a Troupe


Like say, but wait for a response of a given type R

Simply calls say then expect.


Similar to @async, but notifies the calling Actor if it fails.

This allows you to create an asynchronous Task without waiting on it to check for errors. If an exception is thrown, the Actor will send AsyncFail! to itself. By default this will cause TaskFailedException to be thrown thus killing the Actor.


Used to capture variables from the parent thread/task

This is a workaround for integrating third party libraries which use Task local storage or similar. By default it does nothing and it is probably best to avoid using it. See enter! and play!.

Note that this is not necessary for getting OS "environment variables", which are typically shared amongst threads.


Perform some action in a temporary Actor

This creates a new Actor, called a Stooge and uses it to perform some action in parallel.


Do not use variables captured from the surrounding scope, pass them as args.... The args may be copied to avoid concurrency violations.


Add a new Actor to the Stage/Play and return its Id. This is usually called by a AbsMinder's Invite! handler.


The Actor struct a is recreated by the new Actor so you can not use it to do a reverse lookup of the Id.


Wait for a message of type R and return it

This will block waiting for a message of the right type. It will cause the Actor to become 'insensitive', meaning that all other messages will be buffered while waiting.

When a message of the right type is recieved, then the buffered messages will be put back in the inbox and the matching message is returned.

In theory this could accept the wrong message if the type matches, but it was from an old request or it was sent for some other reason. One way to avoid this is to delegate the ask request, or the entire operation, to a Stooge which will have a new address.


Create a new Task, Thread or similar primitive


Handle a received message

Usually called by listen! to handle a message taken from the inbox. The user defines new hear methods to handle messages for different Actor-message type combinations.

It is passed a Scene object which has the Actor state type as the first type parameter. By convention this argument is always called s, if you use a different name it may break some non-essential macros. The other parameter is the message, which is usually called msg, unless you have a more appropriate name, and can be of any type (in a local system).

If hear returns a value it will most likely be ignored (unless you override listen!). If you need to respond to a message then use say or ask.


Get the inbox of an Actor

Useful when overriding functions such as listen! or leave!. Otherwise it is quite unusual for the user to call this. You should use say and ask to send messages.

The inbox is how an Actor recieves messages. In a local system the sender directly places a message into the inbox. Currently inboxes are implemented with a Julia Channel which can be safely accessed by multiple threads, however it is generally expected that you don't pop! messages from another actor's inbox unless that actor is dead.


Like play!, but allows you to send and receive messages from the REPL

Calling this will asynchronously start a play and return a 2-tuple of Scene and Task. The Scene can be used to call various methods in the actor system and the task can be checked to see if the actor system has failed.

The function local_addresses can be used to find out what Id a given actor has.


This is only intended for interactive use in the Julia REPL or similar scenario.


julia> using Actors

julia> struct Ponger end

julia> struct Echo

julia> Actors.hear(s::Scene{Ponger}, msg::Echo) = say(s, msg.who, msg.msg)

julia> (s, t) = interact!()
(Scene{Actors.Person}, Task (runnable) @0x00007fafc7dad600)

julia> me(s)

julia> ponger = enter!(s, Ponger())

julia> ask(s, ponger, Echo(me(s), "Echo, echo, ..."), String)
"Echo, echo, ..."

julia> local_addresses(s)
5-element Array{Pair{Int64,DataType},1}:
 1 => Actors.Person
 2 => Actors.Logger{Base.TTY}
 3 => Actors.PassiveMinder{Id{Actors.Logger{Base.TTY},Union{Leave!, Actors.LogDied!, LogInfo!}}}
 4 => Actors.InteractivePlay
 5 => Ponger

Start a minimal actor system which you can interact with from the REPL


Request an actor be created with the given state and return the new Id. This is just a wrapper for sending Invite! to the current actor's minder and waiting for a response.


Signal that the current Actor should exit (leave)

Usually this closes the inbox which will cause the actor to exit once it has processed any messages it already received. Some actors (e.g Stage) have a grace period where they will continue to accept new messages.

If you wish to exit immediately then throw an exception.

Also see Leave!.


Take messages from the inbox and process them

By default this simply takes messages from the inbox and calls hear on them. However you may wish to process some messages specially or do some work inbetween messages, in which case you can override this for a given Actor type.

As a general rule, you should make sure to call hear on a message if you can't process it some other way. Otherwise you will prevent some standard messages from working (such as Leave!).


Return a list of all the Ids and what type of Actor they point to


This is only intended for interactive use in the REPL or for diagnostics.


Get the address of an Actor's minder

When called on the Scene it will get the current Actor's minder. If called on an Id it will get the minder of the Actor pointed to by the address.


It is generally not thread-safe to change Actor.minder. However you can re-assign a minder's Id to another actor.

See AbsMinder.


Safely get the current Actor's state

Usually the user passes the Scene to this and gets the executing Actor's state in return.!Method

Start the 'Actor System' or a single Actor

Typically the user calls this method on some value which is used as the 'play' Actor state. This then blocks the calling thread until the Stage is sent Leave! or dies due to an error which was allowed to propagate.

This is also called by enter!, in a new Thread/Task, to run a single Actor. Nothing should happen before or after play! so it contains the Actor's full lifetime (excluding Julia internals).

The liftime of the Actor looks something like:

  1. prologue!
  2. listen! (unless prologue! errors)
  3. epilogue! (unless listen! errors)

Then, if there is an error

  1. dieing_breath!

You can override any of the above, so if you are forced to override play!(s::Scene, env) this is considered a library design error. Usually if you feel the need to override any of these, then you should solve the problem with AbsMinder or more message passing instead.


Send a message asynchronously

This returns immediately and doesn't guarantee the message is processed by the actor specified by to. Nor does it guarantee messages will be delivered in the order say is called.

This may throw an error if, for example, to only accepts certain message types.

This doesn't expect a response from to. For that see ask.


Broadcast a message to a plain vector of actors


Like say, but less likely to throw an exception if to is dead. This is commonly useful when an unexpected error has occurred and you want to perform some cleanup without knowing which actors are still alive. Under normal operation you should expect other actors to be alive if you are sending them a message.


If, for example, to exceeds the highest known ID in the local Stage then this will still throw a BoundsError. This is to help prevent silent errors.