insanitybit/aktors

Type safe actors

insanitybit opened this issue · 3 comments

There are two significant problems with Aktors as it stands:

  1. My assumption is that performance is considerably hurt by dynamic dispatch used rampantly

  2. You can send a message to an actor that it can not handle, and this is a runtime failure

Both of these are solved with a type safe actor system, one where you can determine at compile time what messages an actor can handle.

I think that borrowing from Pony is the way to go, as they have an incredibly ergonomic, typesafe actor system.

Having played around with the idea I think what I want is something along these lines:

Take this non-actor code:

struct Foo {
    state: u64
}

impl Foo {
    fn do_a_thing(thing: u64) {
        // do stuff
    }
}

and generate something like this:

enum FooActorMessage {
    DoAThing{ thing: u64 }
}

struct FooActor {
    mailbox: Queue
}

impl FooActor {
    fn do_a_thing(thing: u64) {
        let msg = FooActorMessage{ thing: thing };
        mailbox.send(msg);
    }
}

This would maintain type safety and really cleanly define the concept of behaviors as separate functions.

The problem is, how does one respond? There must be a Sender where A is another actor reference type.

This is where Actor Traits will come in. Given a Trait implemented by an Actor a message type M will be generated for that trait. Therefor you can respond to any actor given that it implements A.

trait SomeTrait {
    // u64 for processing, Sender to the Trait SomeTrait for returning values
    fn do_trait_thing(u64, SomeTrait);
}

enum SomeTraitActorMessage {
    DoTraitThing{ u64, SomeTrait }
}

struct FooActor {
    mailbox: Queue
}

impl FooActor {
    fn do_a_thing(thing: u64, sender: SomeTrait) {
        let msg = DoTraitThing{ thing, sender };
        mailbox.send(msg);
    }
}

That's a rough sketch of the concept. All of this will have to be generated via macros, but it should provide a nice generic type safe actor system.

This will also mean generating a 'dispatch' or 'on_message' function in the Foo impl that takes messages off of the queue and calls the appropriate function.

https://github.com/insanitybit/derive_aktor

Going to mess around with the concept in that repo.