robots/actors/
actor_ref.rs1use std::any::Any;
2use std::sync::Arc;
3
4use actors::{InnerMessage, Message, SystemMessage};
5use actors::actor_cell::ActorCell;
6use actors::cthulhu::Cthulhu;
7
8#[derive(Debug, Eq, Hash, PartialEq)]
9pub enum ActorPath {
13 Local(String),
15 Distant(ConnectionInfo),
17}
18
19impl ActorPath {
20 pub fn new_local(path: String) -> Arc<ActorPath> {
22 Arc::new(ActorPath::Local(path))
23 }
24
25 pub fn new_distant(distant_logical_path: String, addr_port: String) -> Arc<ActorPath> {
27 Arc::new(ActorPath::Distant(
28 ConnectionInfo {
29 distant_logical_path: distant_logical_path,
30 addr_port: addr_port,
31 }))
32 }
33
34 pub fn logical_path(&self) -> &String {
38 match *self {
39 ActorPath::Local(ref s) => s,
40 ActorPath::Distant(ref c) => &(c.distant_logical_path),
41 }
42 }
43
44 pub fn child(&self, name: String) -> Arc<ActorPath> {
48 match *self {
49 ActorPath::Local(ref s) => {
50 let path = format!("{}/{}", s, name);
51 ActorPath::new_local(path)
52 },
53 ActorPath::Distant(_) => panic!("Cannot create a child for a distant actor."),
54 }
55 }
56}
57
58#[derive(Debug, Eq, Hash, PartialEq)]
59pub struct ConnectionInfo {
66 distant_logical_path: String,
67 addr_port: String,
68}
69
70
71impl ConnectionInfo {
72 pub fn distant_logical_path(&self) -> &String {
74 &self.distant_logical_path
75 }
76 pub fn addr_port(&self) -> &String {
78 &self.addr_port
79 }
80}
81
82#[derive(Clone)]
83enum InnerActor {
84 Cthulhu(Cthulhu),
85 Actor(ActorCell),
86}
87
88pub struct ActorRef {
96 inner_actor: Option<InnerActor>,
97 path: Arc<ActorPath>,
98}
99
100impl ActorRef {
101 pub fn new_distant(path: Arc<ActorPath>) -> ActorRef {
103 ActorRef {
104 inner_actor: None,
105 path: path,
106 }
107 }
108
109 pub fn with_cthulhu(cthulhu: Cthulhu) -> ActorRef {
111 let path = ActorPath::new_local("/".to_owned());
112 ActorRef {
113 inner_actor: Some(InnerActor::Cthulhu(cthulhu)),
114 path: path,
115 }
116 }
117
118 pub fn with_cell(cell: ActorCell, path: Arc<ActorPath>) -> ActorRef {
120 ActorRef {
121 inner_actor: Some(InnerActor::Actor(cell)),
122 path: path,
123 }
124 }
125
126 pub fn receive_system_message(&self, system_message: SystemMessage) {
129 info!("{} receiving a system message", self.path().logical_path());
130 let inner = self.inner_actor.as_ref().expect("Tried to put a system message in the mailbox of a distant actor.");
131 match *inner {
132 InnerActor::Actor(ref actor) => actor.receive_system_message(system_message),
133 InnerActor::Cthulhu(ref cthulhu) => cthulhu.receive_system_message(),
134 };
135 }
136
137 pub fn receive(&self, message: InnerMessage, sender: ActorRef) {
139 info!("{} receiving a message", self.path().logical_path());
140 let inner = self.inner_actor.as_ref().expect("Tried to put a message in the mailbox of a distant actor.");
141 match *inner {
142 InnerActor::Actor(ref actor) => actor.receive_message(message, sender),
143 InnerActor::Cthulhu(ref cthulhu) => cthulhu.receive(),
144 };
145 }
146
147 pub fn handle(&self) {
149 info!("{} handling a message", self.path().logical_path());
150 let inner = self.inner_actor.as_ref().expect("");
151 match *inner {
152 InnerActor::Actor(ref actor) => actor.handle_envelope(),
153 InnerActor::Cthulhu(ref cthulhu) => cthulhu.handle(),
154 };
155 }
156
157 pub fn path(&self) -> Arc<ActorPath> {
159 self.path.clone()
160 }
161
162 pub fn tell_to<MessageTo: Message>(&self, to: ActorRef, message: MessageTo) {
164 info!("{} is sending a message to {}", self.path().logical_path(), to.path().logical_path());
165 let message: Box<Any + Send> = Box::new(message);
166 to.receive(InnerMessage::Message(message), self.clone())
167 }
168}
169
170impl Clone for ActorRef {
171 fn clone(&self) -> ActorRef {
172 ActorRef {
173 inner_actor: self.inner_actor.clone(),
174 path: self.path.clone(),
175 }
176 }
177}