I’m happy to announce the release of Actors 0.2 together with two actor infrastructure libraries GenServers and Guards.
Actors
: Concurrency based on the Actor Model
Actors
implements the classical Actor model in Julia. It
- builds on Julia’s concurrency primitives,
- provides a message based programming model for making concurrency easy to understand and reason about and
- integrates well with Julia’s features for multi-threading and distributed computing.
Actors
expresses actor behavior as a function or functor applied partially to some (acquaintance) arguments. The behavior gets executed with further (communication) arguments from an arriving message. That means Actors
makes it easy to build function servers.
Ping-pong
Let me show you that with a game played concurrently:
using Actors, Printf, Random
import Actors: spawn
struct Player{S,T}
name::S
capa::T
end
struct Ball{T,S,L}
diff::T
name::S
from::L
end
struct Serve{L}
to::L
end
function (p::Player)(prn, b::Ball)
if p.capa ≥ b.diff
send(b.from, Ball(rand(), p.name, self()))
send(prn, p.name*" serves "*b.name)
else
send(prn, p.name*" looses ball from "*b.name)
end
end
function (p::Player)(prn, s::Serve)
send(s.to, Ball(rand(), p.name, self()))
send(prn, p.name*" serves ")
end
A player is a functor with two methods. If he can handle a ball, he sends it back, if it is too difficult, he looses it.
Now let’s play: In order to get reproducible results we initialize our random generator on each thread and start the players on assigned threads.
The print server prn
gets an anonymous function as behavior. We start two players ping
and pong
with the print server’s link as acquaintance. We start the game by sending ping
the :serve
command and the address of pong
:
@threads for i in 1:nthreads()
Random.seed!(2021+threadid())
end
prn = spawn(s->print(@sprintf("%s\n", s)))
ping = spawn(Player("Ping", 0.8), prn, thrd=3)
pong = spawn(Player("Pong", 0.75), prn, thrd=4)
send(ping, Serve(pong))
We get
Ping serves
Pong serves Ping
Ping serves Pong
Pong serves Ping
Ping serves Pong
Pong looses ball from Ping
Actors has much more. Please look at it. Documentation and examples are nice. Not least it provides a modern interface to actors based on a messaging protocol. That can be enhanced by further libraries.
Guards
: Servers for Mutable Variables
Guards
is an Actors protocol for serving mutable variables to multiple threads and distributed workers so that they can be accessed concurrently. It has a nice interface and can work almost behind the scenes.
GenServers
: Generic Servers
With GenServers
you can easily implement your own server. You write an implementation module with an interface and callback functions based on a template, start a :genserver
actor with it and you have server for your thing, which can be safely accessed from multiple threads and distributed workers.
What is Still Missing?
For becoming more mature
- we need yet to work on the interface between actor libraries,
- we must work on error handling, actor supervision and monitoring.
Those are next steps. Please try it out, tell what you think of it and join the journey.
Edit: improved the ping-pong example after a hint from @tisztamo