pub struct Process<M, S = Bincode> { /* private fields */ }
Expand description
Processes are isolated units of compute.
In lunatic, all code runs inside processes. Processes run concurrently and communicate via message passing.
Lunatic’s processes should not be confused with operating system processes. Processes in lunatic are extremely lightweight in terms of memory and CPU (even compared to threads as used in many other programming languages). Because of this, it is not uncommon to have tens or even hundreds of thousands of processes running simultaneously.
The Process
type allows us to spawn new processes from rust functions.
There are two kinds of processes:
- Mailbox based processes
- Protocol based processes
They are differentiated by the second argument of the entry function.
Mailbox based processes
A mailbox process takes a Mailbox
that can only receive
messages of one type.
Example
let child = Process::spawn(1, |capture, mailbox: Mailbox<i32>| {
assert_eq!(capture, 1);
assert_eq!(mailbox.receive(), 2);
});
child.send(2);
Processes don’t share any memory and messages sent between them need to be
serialized. By default, the Bincode
serializer is used, but other
serializers that implement the CanSerialize
trait can be used instead.
The serializer just needs to be added to the Mailbox
type (e.g. Mailbox<i32, MessagePack>
).
Processes can also be linked together using the
spawn_link
function. This means that if one of them
fails (panics) the other will be killed too. It is always recommended to
spawn linked processes when they depend on each other. That way we can avoid
one process forever waiting on a message from another process that doesn’t
exist anymore.
Protocol based processes
A protocol process takes a Protocol
that can
define a sequence of messages that will be exchanged between two processes.
This is also known as a session type. The child will get a reference to the
protocol and the parent will get a reference to the opposite protocol.
Example
type AddProtocol = Recv<i32, Recv<i32, Send<i32, End>>>;
let child = Process::spawn(1, |capture: i32, protocol: Protocol<AddProtocol>| {
assert_eq!(capture, 1);
let (protocol, a) = protocol.receive();
let (protocol, b) = protocol.receive();
let _ = protocol.send(capture + a + b);
});
let child = child.send(2);
let child = child.send(2);
let (_, result) = child.receive();
assert_eq!(result, 5);
The rust type system guarantees that the all messages are sent in the correct order and are of correct type. Code that doesn’t follow the protocol would not compile.
Same as the mailbox, the protocol based process can choose another
serializer (e.g. Protocol<AddProtocol, MessagePack>
).
If a protocol based process is dropped before the End
state is reached,
the drop will panic.
Implementations§
source§impl<M, S> Process<M, S>
impl<M, S> Process<M, S>
sourcepub unsafe fn new(node_id: u64, process_id: u64) -> Self
pub unsafe fn new(node_id: u64, process_id: u64) -> Self
Creates a new process reference from a node_id and process_id.
Safety
When creating a process from raw IDs you will need to manually specify the right types.
sourcepub unsafe fn this() -> Self
pub unsafe fn this() -> Self
Return reference to self.
Safety
The right type needs to be manually specified for the deserializer to know what messages to expect.
sourcepub fn is_alive(&self) -> bool
pub fn is_alive(&self) -> bool
Returns true
for processes on the local node that are running.
Panics if called on a remote process.
sourcepub fn spawn<C, T>(capture: C, entry: fn(_: C, _: T)) -> T::Processwhere
S: CanSerialize<C> + CanSerialize<ProtocolCapture<C>>,
T: IntoProcess<M, S> + NoLink,
pub fn spawn<C, T>(capture: C, entry: fn(_: C, _: T)) -> T::Processwhere S: CanSerialize<C> + CanSerialize<ProtocolCapture<C>>, T: IntoProcess<M, S> + NoLink,
Spawn a process.
sourcepub fn spawn_node<C, T>(
node_id: u64,
capture: C,
entry: fn(_: C, _: T)
) -> T::Processwhere
S: CanSerialize<C> + CanSerialize<ProtocolCapture<C>>,
T: IntoProcess<M, S> + NoLink,
pub fn spawn_node<C, T>( node_id: u64, capture: C, entry: fn(_: C, _: T) ) -> T::Processwhere S: CanSerialize<C> + CanSerialize<ProtocolCapture<C>>, T: IntoProcess<M, S> + NoLink,
Spawn a process on a remote node.
sourcepub fn spawn_node_config<C, T>(
node_id: u64,
config: &ProcessConfig,
capture: C,
entry: fn(_: C, _: T)
) -> T::Processwhere
S: CanSerialize<C> + CanSerialize<ProtocolCapture<C>>,
T: IntoProcess<M, S> + NoLink,
pub fn spawn_node_config<C, T>( node_id: u64, config: &ProcessConfig, capture: C, entry: fn(_: C, _: T) ) -> T::Processwhere S: CanSerialize<C> + CanSerialize<ProtocolCapture<C>>, T: IntoProcess<M, S> + NoLink,
Spawn a process on a remote node.
sourcepub fn spawn_link<C, T>(capture: C, entry: fn(_: C, _: T)) -> T::Processwhere
S: CanSerialize<C> + CanSerialize<ProtocolCapture<C>>,
T: IntoProcess<M, S>,
pub fn spawn_link<C, T>(capture: C, entry: fn(_: C, _: T)) -> T::Processwhere S: CanSerialize<C> + CanSerialize<ProtocolCapture<C>>, T: IntoProcess<M, S>,
Spawn a linked process.
sourcepub fn spawn_link_tag<C, T>(
capture: C,
tag: Tag,
entry: fn(_: C, _: T)
) -> T::Processwhere
S: CanSerialize<C> + CanSerialize<ProtocolCapture<C>>,
T: IntoProcess<M, S>,
pub fn spawn_link_tag<C, T>( capture: C, tag: Tag, entry: fn(_: C, _: T) ) -> T::Processwhere S: CanSerialize<C> + CanSerialize<ProtocolCapture<C>>, T: IntoProcess<M, S>,
Spawn a linked process with a tag.
Allows the caller to provide a tag for the link.
sourcepub fn spawn_config<C, T>(
config: &ProcessConfig,
capture: C,
entry: fn(_: C, _: T)
) -> T::Processwhere
S: CanSerialize<C> + CanSerialize<ProtocolCapture<C>>,
T: IntoProcess<M, S> + NoLink,
pub fn spawn_config<C, T>( config: &ProcessConfig, capture: C, entry: fn(_: C, _: T) ) -> T::Processwhere S: CanSerialize<C> + CanSerialize<ProtocolCapture<C>>, T: IntoProcess<M, S> + NoLink,
Spawn a process with a custom configuration.
sourcepub fn spawn_link_config<C, T>(
config: &ProcessConfig,
capture: C,
entry: fn(_: C, _: T)
) -> T::Processwhere
S: CanSerialize<C> + CanSerialize<ProtocolCapture<C>>,
T: IntoProcess<M, S>,
pub fn spawn_link_config<C, T>( config: &ProcessConfig, capture: C, entry: fn(_: C, _: T) ) -> T::Processwhere S: CanSerialize<C> + CanSerialize<ProtocolCapture<C>>, T: IntoProcess<M, S>,
Spawn a linked process with a custom configuration.
sourcepub fn spawn_link_config_tag<C, T>(
config: &ProcessConfig,
capture: C,
tag: Tag,
entry: fn(_: C, _: T)
) -> T::Processwhere
S: CanSerialize<C> + CanSerialize<ProtocolCapture<C>>,
T: IntoProcess<M, S>,
pub fn spawn_link_config_tag<C, T>( config: &ProcessConfig, capture: C, tag: Tag, entry: fn(_: C, _: T) ) -> T::Processwhere S: CanSerialize<C> + CanSerialize<ProtocolCapture<C>>, T: IntoProcess<M, S>,
Spawn a linked process with a custom configuration & provide tag for linking.
sourcepub fn register<N: ProcessName>(&self, name: &N)
pub fn register<N: ProcessName>(&self, name: &N)
Register process under a name.
source§impl<M, S> Process<M, S>where
S: CanSerialize<M>,
impl<M, S> Process<M, S>where S: CanSerialize<M>,
sourcepub fn send(&self, message: M)
pub fn send(&self, message: M)
Send a message to the process.
Panics
This function will panic if the received message can’t be serialized
into M
with serializer S
.
sourcepub fn send_after(&self, message: M, duration: Duration) -> TimerRef
pub fn send_after(&self, message: M, duration: Duration) -> TimerRef
Send a message to the process after the specified duration has passed.
Panics
This function will panic if the received message can’t be serialized
into M
with serializer S
.
Trait Implementations§
source§impl<'de, M, S> Deserialize<'de> for Process<M, S>
impl<'de, M, S> Deserialize<'de> for Process<M, S>
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where __D: Deserializer<'de>,
source§impl<M, S> PartialEq<Process<M, S>> for Process<M, S>
impl<M, S> PartialEq<Process<M, S>> for Process<M, S>
Processes are equal if their process id and node id are equal.
impl<M, S> Copy for Process<M, S>
impl<M, S> Eq for Process<M, S>
Process equality comparison is an equivalence relation