Expand description
The Veecle OS runtime.
This crate contains the main building blocks for any Veecle OS application. Veecle OS applications are composed of Actor
s,
that use the Reader
and Writer
types to communicate with each other within the runtime.
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::convert::Infallible;
use std::fmt::Debug;
use veecle_os_runtime::{Reader, Storable, Writer};
#[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>, pong: Reader<'_, Pong>) -> Infallible {
let mut value = 0;
ping.write(Ping { value }).await;
let mut pong = pong.wait_init().await;
loop {
ping.write(Ping { value }).await;
value += 1;
pong.wait_for_update().await.read(|pong| {
println!("Pong: {}", pong.value);
});
}
}
#[veecle_os_runtime::actor]
async fn pong_actor(mut pong: Writer<'_, Pong>, ping: Reader<'_, Ping>) -> Infallible {
let mut ping = ping.wait_init().await;
loop {
let ping = ping.wait_for_update().await.read_cloned();
println!("Ping: {}", ping.value);
let data = Pong { value: ping.value };
pong.write(data).await;
}
}
futures::executor::block_on(
veecle_os_runtime::execute! {
store: [Ping, Pong],
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.
Macros§
- execute
- Execute a given set of actors without heap allocation.
Structs§
- Exclusive
Reader - Exclusive reader for a
Storable
type. - Initialized
Reader - Reader for a
Storable
type. - Reader
- Reader for a
Storable
type. - Writer
- Writer for a
Storable
type.
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
Reader
s,ExclusiveReader
s orInitializedReader
s. - 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
Reader
s andWriter
s in anActor
.