From 5b0925033ec1fe15d0e37429325ed7fe98d1f11e Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 20 Oct 2012 21:10:38 -0700 Subject: [PATCH] Sketch out a very simple actor API --- src/servo/servo.rc | 1 + src/servo/util/actor.rs | 109 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 src/servo/util/actor.rs diff --git a/src/servo/servo.rc b/src/servo/servo.rc index d9b6f2c5950..aac0dc3b43b 100755 --- a/src/servo/servo.rc +++ b/src/servo/servo.rc @@ -130,6 +130,7 @@ pub mod util { pub mod url; pub mod vec; pub mod range; + pub mod actor; } pub mod opts; diff --git a/src/servo/util/actor.rs b/src/servo/util/actor.rs new file mode 100644 index 00000000000..c13684836d9 --- /dev/null +++ b/src/servo/util/actor.rs @@ -0,0 +1,109 @@ +/*! +An actor type +*/ + +use pipes::{Port, Chan, SharedChan, stream}; + +/** +The client reference to an actor + +Actors are only referred to by opaque handles parameterized +over the actor's message type, which can be considered the +actor's interface. +*/ +struct ActorRef { + chan: Chan, +} + +impl ActorRef { + fn send(msg: M) { + self.chan.send(move msg); + } +} + +/// The local actor interface +trait Actor { + fn handle(msg: M) -> bool; +} + +/// A helper function used by actor constructors +fn spawn, M: Send>(f: ~fn() -> A) -> ActorRef { + let (chan, port) = stream(); + do task::spawn |move f, move port| { + let actor = f(); + loop { + let msg = port.recv(); + if !actor.handle(move msg) { + break; + } + } + } + + return ActorRef { + chan: move chan + } +} + +struct SharedActorRef { + chan: SharedChan +} + +impl SharedActorRef { + fn send(msg: M) { + self.chan.send(move msg); + } +} + +fn SharedActorRef(actor: ActorRef) -> SharedActorRef { + let chan = match move actor { + ActorRef { + chan: move chan + } => { + move chan + } + }; + + SharedActorRef { + chan: SharedChan(move chan) + } +} + +#[cfg(test)] +mod test { + + enum HelloMsg { + Exit(Chan<()>) + } + + struct HelloActor { + name: ~str + } + + impl HelloActor: Actor { + fn handle(msg: HelloMsg) -> bool { + match msg { + Exit(chan) => { + chan.send(()); + return false; + } + } + } + } + + fn HelloActor(name: ~str) -> ActorRef { + do spawn |move name| { + HelloActor { + name: copy name + } + } + } + + + #[test] + fn test_exit() { + let actor = HelloActor(~"bob"); + let (chan, port) = stream(); + actor.send(Exit(move chan)); + port.recv(); + } +} \ No newline at end of file