Crate runtime
Expand description
The Veecle OS runtime.
This crate contains the main building blocks for any Veecle OS application.
Veecle OS applications are composed of Actors that communicate with each other through
slots.
Slots come in different implementations; see single_writer for a slot implementation
with one writer and multiple readers, and mpsc for multiple writers with a single reader.
This crate is meant to be used with asynchronous programming, which means that actors are expected to be async functions. For example, it will be ensured that an actor does not update a value till all its readers had the chance to read its latest state.
§Example
The following Veecle OS application consists of two actors, PingActor and PongActor, that communicate with each
other.
use std::fmt::Debug;
use veecle_os_runtime::single_writer::{Reader, Writer};
use veecle_os_runtime::{Never, Storable};
#[derive(Debug, Clone, PartialEq, Eq, Default, Storable)]
pub struct Ping {
value: u32,
}
#[derive(Debug, Clone, PartialEq, Eq, Default, Storable)]
pub struct Pong {
value: u32,
}
#[veecle_os_runtime::actor]
async fn ping_actor(mut ping: Writer<'_, Ping>, mut pong: Reader<'_, Pong>) -> Never {
let mut value = 0;
ping.write(Ping { value }).await;
loop {
ping.write(Ping { value }).await;
value += 1;
pong.read_updated(|pong| {
println!("Pong: {}", pong.value);
}).await;
}
}
#[veecle_os_runtime::actor]
async fn pong_actor(mut pong: Writer<'_, Pong>, mut ping: Reader<'_, Ping>) -> Never {
loop {
let ping = ping.read_updated_cloned().await;
println!("Ping: {}", ping.value);
let data = Pong { value: ping.value };
pong.write(data).await;
}
}
futures::executor::block_on(
veecle_os_runtime::execute! {
actors: [
PingActor,
PongActor,
]
}
)§Output
The expected output for this example would be a sequence of ping/pong messages like the following:
Ping: 1
Pong: 1
Ping: 2
Pong: 2
Ping: 3
Pong: 3
...§Execution
See how the PongActor waits for Ping to be written by the PingActor.
If that were not the behavior, we would see Ping: 0 as the very first output, since Ping defaults to zero.
The same would happen with the PingActor: if it were not waiting for Pong updates, its immediate action after
writing Ping would be to display Pong: 0. Waiting for updates ensures us that only written values are read.
On the other hand, writing always yields for other woken futures to be executed before performing the write operation. The only exception is the very first write, since there is no latest value for readers to read.
Modules§
- memory_
pool - An interrupt/thread-safe memory pool.
- mpsc
- MPSC (multiple-producer, single-consumer) slot implementation.
- single_
writer - Single-writer slot implementation.
Macros§
- execute
- Execute a given set of actors without heap allocation.
Structs§
- Modify
- A wrapper around
&mut Option<T>that allows inspecting or modifying the value.
Enums§
- Never
- A type that can never be constructed.
Traits§
- Actor
- Actor interface.
- Combinable
Reader - A marker trait for types that can be used with
CombineReaders, see that for more details. - Combine
Readers - Allows combining (nearly) arbitrary amounts of
Readers orExclusiveReaders. - Storable
- Marks a type as an identifier for the inner
DataType, which can be transferred via a slot. - Store
Request - Allows requesting a (nearly) arbitrary amount of readers and writers in an
Actor.