# \[ANN\] Actors 0.2, GenServers and Guards

**URL:** <https://discourse.julialang.org/t/ann-actors-0-2-genservers-and-guards/52056>\
**Category:** Package Announcements\
**Tags:** multithreading, distributed, concurrency, actors\
**Created:** [December 18, 2020, 4:21pm UTC](https://discourse.julialang.org/t/ann-actors-0-2-genservers-and-guards/52056 "2020-12-18T16:21:20Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)\
**Post date:** [December 18, 2020, 4:21pm UTC](https://discourse.julialang.org/t/ann-actors-0-2-genservers-and-guards/52056/1 "2020-12-18T16:21:20Z")

</div>

I’m happy to announce the release of [Actors](https://github.com/JuliaActors/Actors.jl) 0.2 together with two actor infrastructure libraries [GenServers](https://github.com/JuliaActors/GenServers.jl) and [Guards](https://github.com/JuliaActors/Guards.jl).

## [`Actors`](https://github.com/JuliaActors/Actors.jl): Concurrency based on the Actor Model

`Actors` implements the classical [Actor model](https://en.wikipedia.org/wiki/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:

```julia
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`:

```julia
@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

```julia
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](https://juliaactors.github.io/Actors.jl/stable/) 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`](https://github.com/JuliaActors/Guards.jl): 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`](https://github.com/JuliaActors/GenServers.jl): 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

1. we need yet to work on the interface between actor libraries,
2. 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

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [December 19, 2020, 8:19am UTC](https://discourse.julialang.org/t/ann-actors-0-2-genservers-and-guards/52056/2 "2020-12-19T08:19:35Z")

</div>

Wow, @pbayer, you’ve been on a coding spree these last weeks!

---

<div class="post-metadata">

**Author:** ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)\
**Post date:** [December 19, 2020, 3:19pm UTC](https://discourse.julialang.org/t/ann-actors-0-2-genservers-and-guards/52056/3 "2020-12-19T15:19:23Z")

</div>

Yes, that has been quite a journey. Due to pandemic times, I could work full-time on it. But

- I could take quite something from `YAActL` and
- creating those two infrastructure libraries has been easy due to the new `Actors` protocol and
- it was also fun 😉.

---

<div class="post-metadata">

**Author:** ![miguelraz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/miguelraz/32/631_2.png) [@miguelraz](https://discourse.julialang.org/u/miguelraz)\
**Post date:** [December 21, 2020, 4:41am UTC](https://discourse.julialang.org/t/ann-actors-0-2-genservers-and-guards/52056/4 "2020-12-21T04:41:13Z")

</div>

Whoah!

---

<div class="post-metadata">

**Author:** ![jcook](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jcook/32/18211_2.png) [@jcook](https://discourse.julialang.org/u/jcook)\
**Post date:** [December 24, 2020, 10:51am UTC](https://discourse.julialang.org/t/ann-actors-0-2-genservers-and-guards/52056/5 "2020-12-24T10:51:38Z")

</div>

I love this package! It’s great to be able to specify which thread or process id to launch Actors onto.

Question: I’ve tried changing

```julia
send(prn, p.name*" looses ball from "*b.name)

```

to

```julia
send(prn, p.name*" looses ball from "*b.from.name)

```

where the ball sender’s `name` is accessed as a field on `from` rather than straight from the `ball` itself. The output then becomes:

```julia
Ping serves

```

only and no game is played (or at least printed to the terminal). Why is this?

---

<div class="post-metadata">

**Author:** ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)\
**Post date:** [December 24, 2020, 11:05am UTC](https://discourse.julialang.org/t/ann-actors-0-2-genservers-and-guards/52056/6 "2020-12-24T11:05:41Z")

</div>

glad to hear that you love it!

In such a case you can do

```julia
julia> Actors.info(pong)
Task (failed) @0x00000001153186d0
type Link has no field name
getproperty(::Link{Channel{Any}}, ::Symbol) at ./Base.jl:33
(::Player{String,Float64})(::Link{Channel{Any}}, ::Ball{Float64,String,Link{Channel{Any}}}) at /Users/paul/.julia/dev/Actors/examples/pingpong.jl:30
....

```

The point is that `from` is a `link` to the actor. You cannot subset it.

---

<div class="post-metadata">

**Author:** ![jcook](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jcook/32/18211_2.png) [@jcook](https://discourse.julialang.org/u/jcook)\
**Post date:** [December 24, 2020, 11:24am UTC](https://discourse.julialang.org/t/ann-actors-0-2-genservers-and-guards/52056/7 "2020-12-24T11:24:51Z")

</div>

Thanks - I understand now. I’ve found Actors very easy to build a mental model around.

One further question: The second argument, `prn`, in `ping = spawn(Player("Ping", 0.8), prn, thrd=3)` is a another `spawn`ed `Link`, which appears to then be the first argument to calls to the `Player` functors. Is this how additional arguments to functors are configured?

---

<div class="post-metadata">

**Author:** ![StatisticalMouse](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/statisticalmouse/32/43370_2.png) [@StatisticalMouse](https://discourse.julialang.org/u/StatisticalMouse)\
**Post date:** [December 24, 2020, 11:41am UTC](https://discourse.julialang.org/t/ann-actors-0-2-genservers-and-guards/52056/8 "2020-12-24T11:41:29Z")

</div>

I have a slightly more generic question about actors. I can easily see how they can be used for instance for handling streaming data, but can they be used to build algorithms of some kind?

---

<div class="post-metadata">

**Author:** ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)\
**Post date:** [December 24, 2020, 12:31pm UTC](https://discourse.julialang.org/t/ann-actors-0-2-genservers-and-guards/52056/9 "2020-12-24T12:31:51Z")

</div>

> [@jcook](#):
>
> Is this how additional arguments to functors are configured?

Yes, `prn` is an additional “acquaintance” argument. The actor holds that in its state. You need to send it only the missing arguments to cause it to execute the behavior (functor).

If you do `spawn(Player("Ping", 0.8), prn, thrd=3)`, you partially apply the `Player` functor with its acquaintances `"Ping", 0.8` to one further acquaintance `prn`. Then later it gets the `Ball` as communication argument.

---

<div class="post-metadata">

**Author:** ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)\
**Post date:** [December 24, 2020, 12:47pm UTC](https://discourse.julialang.org/t/ann-actors-0-2-genservers-and-guards/52056/10 "2020-12-24T12:47:36Z")

</div>

> [@StatisticalMouse](#):
>
> can they be used to build algorithms of some kind?

What spontaneously comes to my mind, is the following:

1. Actors can operate as _function servers_. They can do a calculation in parallel on some other thread or worker and serve it to your algorithm. In this regard they are similar to tasks.
2. But actors hold also _state_. Therefore they can serve also _variables_. If you have an algorithm needing access to a variable - maybe in parallel on multiple threads or workers - you can have an actor serving it. This is a composable alternative to a lock. It doesn’t need a lock, but cares the same that the variable is accessed strictly sequentially.
3. Then I think, actors are great to model stochastic processes and systems.
4. You can model with actors the typical concurrency conundrums: dining philosophers, sleeping barber, producer-consumer problem … Also those are algorithms.

---

<div class="post-metadata">

**Author:** ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)\
**Post date:** [December 25, 2020, 8:55am UTC](https://discourse.julialang.org/t/ann-actors-0-2-genservers-and-guards/52056/11 "2020-12-25T08:55:58Z")

</div>

Some further thoughts on this:

> [@pbayer](#):
>
> - Actors can operate as _function servers_ . …
> - But actors hold also _state_ . Therefore they can serve also _variables_ .

Those two features give the possibility to compose actors hierarchically and sequentially into algorithms as we normally expect. As I mentioned actors being lock free are better composable. But otherwise you may not gain much with actors for hierarchical and sequential composition.

But a whole new game is to compose actors asynchronously. That gives you the access to

- [distributed algorithms](https://en.wikipedia.org/wiki/Distributed_algorithm),
- stuff like mentioned in my points 3 and 4,
- fault-tolerance

and much more. For those applications actors usually give you a programming model easier to understand and reason about.

For distributed algorithms you may be interested to look at [_Distributed Algorithms for Message-Passing Systems_](http://www.amazon.com/dp/B00DPE0EXG).

---

<div class="post-metadata">

**Author:** ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)\
**Post date:** [January 27, 2021, 6:14pm UTC](https://discourse.julialang.org/t/ann-actors-0-2-genservers-and-guards/52056/12 "2021-01-27T18:14:19Z")

</div>

Today in the Multithreading BoF I gave a presentation on [Actors.jl](https://github.com/JuliaActors/Actors.jl). The slides are at:

[https://github.com/JuliaActors/Actors.jl/blob/master/docs/slides/Actors\_2020-01-27.key.pdf](https://github.com/JuliaActors/Actors.jl/blob/master/docs/slides/Actors_2020-01-27.key.pdf)

enjoy!

---

<div class="post-metadata">

**Author:** ![tisztamo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tisztamo/32/16200_2.png) [@tisztamo](https://discourse.julialang.org/u/tisztamo)\
**Post date:** [January 30, 2021, 3:31pm UTC](https://discourse.julialang.org/t/ann-actors-0-2-genservers-and-guards/52056/13 "2021-01-30T15:31:39Z")

</div>

Great!

What is the Multithreading BoF?

---

<div class="post-metadata">

**Author:** ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)\
**Post date:** [January 30, 2021, 3:52pm UTC](https://discourse.julialang.org/t/ann-actors-0-2-genservers-and-guards/52056/14 "2021-01-30T15:52:08Z")

</div>

> [@tisztamo](#):
>
> What is the Multithreading BoF?

It is an event every three weeks in the [Julia calendar](https://julialang.org/community/) and organized by @jameson via the Julia Slack multithreading channel.
