Skip to content

Instantly share code, notes, and snippets.

@huntc
Last active April 26, 2021 09:15
Show Gist options
  • Save huntc/97985c6bf3f138ca35196423ec8801a0 to your computer and use it in GitHub Desktop.
Save huntc/97985c6bf3f138ca35196423ec8801a0 to your computer and use it in GitHub Desktop.
Actor thoughts
// Re-creates https://doc.akka.io/docs/akka/current/typed/actors.html#first-example
// The messages
struct Greet {
whom: String,
reply_to: ActorRef<Greeted>,
}
struct Greeted {
whom: String,
from: ActorRef<Greet>,
}
struct SayHello {
name: String,
}
// The HelloWorld actor
struct HelloWorld {}
impl Actor<Greet> for HelloWorld {
fn receive(&mut self, context: &mut ActorContext<Greet>, message: &Greet) {
println!("Hello {}!", message.whom);
message.reply_to.tell(Greeted {
whom: message.whom.to_owned(),
from: context.actor_ref.to_owned(),
});
}
}
// The HelloWorldBot actor
struct HelloWorldBot {
greeting_counter: u32,
max: u32,
}
impl Actor<Greeted> for HelloWorldBot {
fn receive(&mut self, context: &mut ActorContext<Greeted>, message: &Greeted) {
let n = self.greeting_counter + 1;
println!("Greeting {} for {}", n, message.whom);
if n == self.max {
context.stop();
} else {
message.from.tell(Greet {
whom: message.whom.to_owned(),
reply_to: context.actor_ref.to_owned(),
});
self.greeting_counter = n;
}
}
}
// The root actor
struct HelloWorldMain {
greeter: Option<ActorRef<Greet>>,
}
impl Actor<SayHello> for HelloWorldMain {
fn receive(&mut self, context: &mut ActorContext<SayHello>, message: &SayHello) {
let greeter = match &self.greeter {
None => {
let greeter = context.spawn(|| Box::new(HelloWorld {}), "greeter");
self.greeter = Some(greeter.to_owned());
greeter
}
Some(greeter) => greeter.to_owned(),
};
let reply_to = context.spawn(
|| {
Box::new(HelloWorldBot {
greeting_counter: 0,
max: 3,
})
},
&message.name,
);
greeter.tell(Greet {
whom: message.name.to_owned(),
reply_to,
});
}
}
// Create a root context, which is essentiallly the actor system. We
// also send a couple of messages for our demo.
let system = ActorContext::<SayHello>::new(
|| Box::new(HelloWorldMain { greeter: None }),
"hello",
dispatcher.to_owned(),
);
system.actor_ref.tell(SayHello {
name: "World".to_string(),
});
system.actor_ref.tell(SayHello {
name: "Mylib".to_string(),
});
// We create an executor along with a dispatcher so our actors can schedule
// their execution.
let dispatcher = ...
/// I have this bit working, but want to tidy it up - suffice to state, it is designed
/// to be adapted for any executor lib.
// Run the dispatcher select function on its own thread. We wait
// for the select function to finish, which will be when will
// tell the "system" (the actor context above) to stop, it is stops
// itself.
let select_thread_dispatcher = dispatcher.to_owned();
let select_thread = thread::spawn(move || select_thread_dispatcher.select());
thread::sleep(Duration::from_millis(500));
dispatcher.stop();
assert!(select_thread.join().is_ok());
@huntc
Copy link
Author

huntc commented Apr 23, 2021

See https://github.com/titanclass/stage for the actual project

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment