Crate veecle_os_runtime

Source
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 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§

ExclusiveReader
Exclusive reader for a Storable type.
InitializedReader
Reader for a Storable type.
Reader
Reader for a Storable type.
Writer
Writer for a Storable type.

Traits§

Actor
Actor interface.
CombinableReader
A marker trait for types that can be used with CombineReaders, see that for more details.
CombineReaders
Allows combining (nearly) arbitrary amounts of Readers, ExclusiveReaders or InitializedReaders.
Storable
Marks a type as an identifier for the inner DataType, which can be transferred via a slot.
StoreRequest
Allows requesting a (nearly) arbitrary amount of Readers and Writers in an Actor.

Attribute Macros§

actor
Generates an Actor from a function.

Derive Macros§

Storable
Implements Storable for a struct or enum.