I’d like to introduce you a simple actor library that implemented based on MAY.

With this library, when create an actor

you don’t need to declare messages that passed into the actor

that passed into the actor you don’t have to implement “actor” interface or trait for your actor.

You just wrap your actual actor struct with the Actor<T> type. It’s like a handle that used to access the actor.

1

2

3

4

5

6

7

8

9

fn it_works () {

let i = 0u32 ;

let a = Actor::new(i);

a.call(|me| *me += 2 );

a.call(|_me| panic! ( "support panic inside" ));

a.call(|me| *me += 4 );



a.view(|me| assert_eq! (*me, 6 ));

}



You send message to the actor with the call API. It accepts a closure that have the &mut T as parameter. So that you can change it’s internal state. The closure would be send to a queue inside the actor, and the actor would execute the closure by a coroutine that associate with it. This API would not block user’s execution and would return immediately.

You can also view the actor internal state by the view API. It accepts a closure that have the &T as parameter, so that you can access the state without modify permission. The closure would be executed by the associated coroutine if there are no other pending messages need to process. And it will block until the closure returns. So during the view stage, you are guaranteed that no others are modifying the actor.

The actor can be cloned to get a new handle, this is just like how Arc<T> works, after all the actor handle got dropped, the associated coroutine will automatically exit.

And you can transmute a &self type unsafely to actor handle Actor<T> . This is convenient when you need to get the actual handle that need to passed to other actors in your implementations.

However, this simple library doesn’t support spawn actors across processes.

For more examples, please visit the repo on github.