Skip to content

Commit fb29cfb

Browse files
committed
Implemented Message trait
1 parent 9db03d1 commit fb29cfb

File tree

7 files changed

+71
-112
lines changed

7 files changed

+71
-112
lines changed

src/bastion/examples/ping/src/main.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ impl Actor for Ping {
3939

4040
while (pong_struct.counter != 3) {
4141
let message = ctx.recv().await?;
42+
message.handle(ctx).await;
4243

43-
// Do something with the message ...
44-
45-
message.ack().await;
4644
self.send(message.path(), "pong", MessageType::Tell).await?;
4745
pong_struct.counter += 1;
46+
47+
message.ack().await;
4848
}
4949

5050
System::stop();

src/bastion/src/actor/context.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use std::sync::Arc;
22

3-
use async_channel::unbounded;
3+
use async_channel::{unbounded, Sender};
44

55
use crate::actor::local_state::LocalState;
66
use crate::actor::state::ActorState;
7-
use crate::mailbox::traits::TypedMessage;
7+
use crate::mailbox::envelope::Envelope;
8+
use crate::mailbox::message::Message;
89
use crate::mailbox::Mailbox;
910
use crate::routing::path::ActorPath;
1011

@@ -19,28 +20,28 @@ pub struct Context {
1920
/// Path to the actor in the system
2021
path: Arc<ActorPath>,
2122
/// Mailbox of the actor
22-
//mailbox: Mailbox<TypedMessage>,
23+
mailbox: Mailbox<Box<dyn Message>>,
2324
/// Local storage for actor's data
2425
local_state: LocalState,
2526
/// Current execution state of the actor
2627
internal_state: ActorState,
2728
}
2829

2930
impl Context {
30-
// FIXME: Pass the correct system_rx instead of the fake one
31-
pub(crate) fn new(path: ActorPath) -> Self {
32-
//let (_system_tx, system_rx) = unbounded();
33-
// let mailbox = Mailbox::new(system_rx);
31+
pub(crate) fn new(path: ActorPath) -> (Self, Sender<Envelope<impl Message>>) {
32+
let (system_tx, system_rx) = unbounded();
3433

3534
let path = Arc::new(path);
35+
let mailbox = Mailbox::new(system_rx);
3636
let local_state = LocalState::new();
3737
let internal_state = ActorState::new();
3838

39-
Context {
39+
let instance = Context {
4040
path,
41-
//mailbox,
41+
mailbox,
4242
local_state,
4343
internal_state,
44-
}
44+
};
45+
(instance, system_tx)
4546
}
4647
}

src/bastion/src/mailbox/envelope.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,34 @@
1+
use std::cell::RefCell;
12
use std::fmt::{self, Debug, Formatter};
23

34
use crate::actor::actor_ref::ActorRef;
4-
use crate::mailbox::message::MessageType;
5-
use crate::mailbox::traits::TypedMessage;
5+
use crate::mailbox::message::{Message, MessageType};
66

77
/// Struct that represents an incoming message in the actor's mailbox.
88
#[derive(Clone)]
99
pub struct Envelope<T>
1010
where
11-
T: TypedMessage,
11+
T: Message,
1212
{
1313
/// The sending side of a channel. In actor's world
1414
/// represented is a message sender. Can be used
1515
/// for acking message when it possible.
1616
sender: Option<ActorRef>,
1717
/// An actual data sent by the channel
18-
message: T,
18+
message: RefCell<Option<T>>,
1919
/// Message type that helps to figure out how to deliver message
2020
/// and how to ack it after the processing.
2121
message_type: MessageType,
2222
}
2323

2424
impl<T> Envelope<T>
2525
where
26-
T: TypedMessage,
26+
T: Message,
2727
{
2828
/// Create a message with the given sender and inner data.
29-
pub fn new(sender: Option<ActorRef>, message: T, message_type: MessageType) -> Self {
29+
pub fn new(sender: Option<ActorRef>, data: T, message_type: MessageType) -> Self {
30+
let message = RefCell::new(Some(data));
31+
3032
Envelope {
3133
sender,
3234
message,
@@ -40,8 +42,14 @@ where
4042
self.message_type.clone()
4143
}
4244

45+
/// Extracts the message data and returns it to the caller. Each further
46+
/// method call will return `None`.
47+
pub fn read(&self) -> Option<T> {
48+
self.message.take()
49+
}
50+
4351
/// Sends a confirmation to the message sender.
44-
pub(crate) async fn ack(&self) {
52+
pub async fn ack(&self) {
4553
match self.message_type {
4654
MessageType::Ack => unimplemented!(),
4755
MessageType::Broadcast => unimplemented!(),
@@ -52,7 +60,7 @@ where
5260

5361
impl<T> Debug for Envelope<T>
5462
where
55-
T: TypedMessage,
63+
T: Message,
5664
{
5765
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
5866
fmt.debug_struct("Message")

src/bastion/src/mailbox/message.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
use std::fmt::Debug;
2+
3+
/// A trait that message needs to implement for typed actors (it
4+
/// forces message to implement the following traits: [`Any`],
5+
/// [`Send`] and [`Debug`]).
6+
///
7+
/// [`Any`]: https://doc.rust-lang.org/std/any/trait.Any.html
8+
/// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
9+
/// [`Debug`]: https://doc.rust-lang.org/std/fmt/trait.Debug.html
10+
pub trait Message: Send + Debug + 'static {}
11+
impl<T> Message for T where T: ?Sized + Send + Debug + 'static {}
12+
113
/// Enum that provides information what type of the message
214
/// being sent through the channel.
315
#[derive(Debug, Copy, Clone, Eq, PartialEq)]

src/bastion/src/mailbox/mod.rs

+29-74
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
mod envelope;
2-
mod state;
1+
pub(crate) mod envelope;
2+
pub(crate) mod state;
33

44
pub mod message;
5-
pub mod traits;
65

76
use std::sync::atomic::AtomicBool;
87
use std::sync::Arc;
@@ -11,14 +10,14 @@ use async_channel::{unbounded, Receiver, Sender};
1110

1211
use crate::error::{BastionError, Result};
1312
use crate::mailbox::envelope::Envelope;
13+
use crate::mailbox::message::Message;
1414
use crate::mailbox::state::MailboxState;
15-
use crate::mailbox::traits::TypedMessage;
1615

1716
/// Struct that represents a message sender.
1817
#[derive(Clone)]
1918
pub struct MailboxTx<T>
2019
where
21-
T: TypedMessage,
20+
T: Message,
2221
{
2322
/// Indicated the transmitter part of the actor's channel
2423
/// which is using for passing messages.
@@ -30,7 +29,7 @@ where
3029

3130
impl<T> MailboxTx<T>
3231
where
33-
T: TypedMessage,
32+
T: Message,
3433
{
3534
/// Return a new instance of MailboxTx that indicates sender.
3635
pub(crate) fn new(tx: Sender<Envelope<T>>) -> Self {
@@ -57,110 +56,66 @@ where
5756
#[derive(Clone)]
5857
pub struct Mailbox<T>
5958
where
60-
T: TypedMessage,
59+
T: Message,
6160
{
62-
/// User guardian sender
63-
user_tx: MailboxTx<T>,
64-
/// User guardian receiver
65-
user_rx: Receiver<Envelope<T>>,
61+
/// Actor guardian sender
62+
actor_tx: MailboxTx<T>,
63+
/// Actor guardian receiver
64+
actor_rx: Receiver<Envelope<T>>,
6665
/// System guardian receiver
6766
system_rx: Receiver<Envelope<T>>,
68-
/// The current processing message, received from the
69-
/// latest call to the user's queue
70-
last_user_message: Option<Envelope<T>>,
71-
/// The current processing message, received from the
72-
/// latest call to the system's queue
73-
last_system_message: Option<Envelope<T>>,
7467
/// Mailbox state machine
7568
state: Arc<MailboxState>,
7669
}
7770

7871
// TODO: Add calls with recv with timeout
7972
impl<T> Mailbox<T>
8073
where
81-
T: TypedMessage,
74+
T: Message,
8275
{
8376
/// Creates a new mailbox for the actor.
8477
pub(crate) fn new(system_rx: Receiver<Envelope<T>>) -> Self {
85-
let (tx, user_rx) = unbounded();
86-
let user_tx = MailboxTx::new(tx);
87-
let last_user_message = None;
88-
let last_system_message = None;
78+
let (tx, actor_rx) = unbounded();
79+
let actor_tx = MailboxTx::new(tx);
8980
let state = Arc::new(MailboxState::new());
9081

9182
Mailbox {
92-
user_tx,
93-
user_rx,
83+
actor_tx,
84+
actor_rx,
9485
system_rx,
95-
last_user_message,
96-
last_system_message,
9786
state,
9887
}
9988
}
10089

101-
/// Forced receive message from user queue
90+
/// Forced receive message from the actor's queue.
10291
pub async fn recv(&mut self) -> Envelope<T> {
103-
let message = self
104-
.user_rx
92+
self.actor_rx
10593
.recv()
10694
.await
10795
.map_err(|e| BastionError::ChanRecv(e.to_string()))
108-
.unwrap();
109-
110-
self.last_user_message = Some(message);
111-
self.last_user_message.clone().unwrap()
96+
.unwrap()
11297
}
11398

114-
/// Try receiving message from user queue
99+
/// Try receiving message from the actor's queue.
115100
pub async fn try_recv(&mut self) -> Result<Envelope<T>> {
116-
if self.last_user_message.is_some() {
117-
return Err(BastionError::UnackedMessage);
118-
}
119-
120-
match self.user_rx.try_recv() {
121-
Ok(message) => {
122-
self.last_user_message = Some(message);
123-
Ok(self.last_user_message.clone().unwrap())
124-
}
125-
Err(e) => Err(BastionError::ChanRecv(e.to_string())),
126-
}
101+
self.actor_rx
102+
.try_recv()
103+
.map_err(|e| BastionError::ChanRecv(e.to_string()))
127104
}
128105

129-
/// Forced receive message from system queue
106+
/// Forced receive message from the internal system queue.
130107
pub async fn sys_recv(&mut self) -> Envelope<T> {
131-
let message = self
132-
.system_rx
108+
self.system_rx
133109
.recv()
134110
.await
135111
.map_err(|e| BastionError::ChanRecv(e.to_string()))
136-
.unwrap();
137-
138-
self.last_system_message = Some(message);
139-
self.last_system_message.clone().unwrap()
112+
.unwrap()
140113
}
141114

142-
/// Try receiving message from system queue
115+
/// Try receiving message from the internal system queue.
143116
pub async fn try_sys_recv(&mut self) -> Result<Envelope<T>> {
144-
if self.last_system_message.is_some() {
145-
return Err(BastionError::UnackedMessage);
146-
}
147-
148-
match self.system_rx.try_recv() {
149-
Ok(message) => {
150-
self.last_system_message = Some(message);
151-
Ok(self.last_system_message.clone().unwrap())
152-
}
153-
Err(e) => Err(BastionError::ChanRecv(e.to_string())),
154-
}
155-
}
156-
157-
/// Returns the last retrieved message from the user channel
158-
pub async fn get_last_user_message(&self) -> Option<Envelope<T>> {
159-
self.last_user_message.clone()
160-
}
161-
162-
/// Returns the last retrieved message from the system channel
163-
pub async fn get_last_system_message(&self) -> Option<Envelope<T>> {
164-
self.last_system_message.clone()
117+
self.system_rx
118+
.try_recv()
119+
.map_err(|e| BastionError::ChanRecv(e.to_string()))
165120
}
166121
}

src/bastion/src/mailbox/traits.rs

-13
This file was deleted.

src/bastion/src/system/global_state.rs

-4
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,11 @@
44
/// transaction memory (or shortly STM) mechanisms to eliminate any
55
/// potential data races and provide consistency across actors.
66
use std::any::{Any, TypeId};
7-
use std::ops::Deref;
87
use std::sync::Arc;
98

109
use lever::sync::atomics::AtomicBox;
1110
use lever::table::lotable::LOTable;
1211

13-
use crate::error::{BastionError, Result};
14-
use std::borrow::Borrow;
15-
1612
#[derive(Debug)]
1713
pub struct GlobalState {
1814
table: LOTable<TypeId, Arc<AtomicBox<Box<dyn Any + Send + Sync>>>>,

0 commit comments

Comments
 (0)