veecle_os_runtime/
lib.rs

1//! The Veecle OS runtime.
2//!
3//! This crate contains the main building blocks for any Veecle OS application.  Veecle OS applications are composed of [`Actor`]s,
4//! that use the [`Reader`] and [`Writer`] types to communicate with each other within the runtime.
5//!
6//! This crate is meant to be used with asynchronous programming, which means that actors are expected to be async
7//! functions. For example, it will be ensured that an actor does not update a value till all its readers had the
8//! chance to read its latest state.
9//!
10//! # Example
11//!
12//! The following Veecle OS application consists of two actors, `PingActor` and `PongActor`, that communicate with each
13//! other.
14//!
15//! ```rust
16//! use std::convert::Infallible;
17//! use std::fmt::Debug;
18//!
19//! use veecle_os_runtime::{Reader, Storable, Writer};
20//!
21//! #[derive(Debug, Clone, PartialEq, Eq, Default, Storable)]
22//! pub struct Ping {
23//!     value: u32,
24//! }
25//!
26//! #[derive(Debug, Clone, PartialEq, Eq, Default, Storable)]
27//! pub struct Pong {
28//!     value: u32,
29//! }
30//!
31//! #[veecle_os_runtime::actor]
32//! async fn ping_actor(mut ping: Writer<'_, Ping>, pong: Reader<'_, Pong>) -> Infallible {
33//!     let mut value = 0;
34//!     ping.write(Ping { value }).await;
35//!
36//!     let mut pong = pong.wait_init().await;
37//!     loop {
38//!         ping.write(Ping { value }).await;
39//!         value += 1;
40//!
41//!         pong.wait_for_update().await.read(|pong| {
42//!             println!("Pong: {}", pong.value);
43//!         });
44//! #       // Exit the application to allow doc-tests to complete.
45//! #       std::process::exit(0);
46//!     }
47//! }
48//!
49//! #[veecle_os_runtime::actor]
50//! async fn pong_actor(mut pong: Writer<'_, Pong>, ping: Reader<'_, Ping>) -> Infallible {
51//!     let mut ping = ping.wait_init().await;
52//!     loop {
53//!         let ping = ping.wait_for_update().await.read_cloned();
54//!         println!("Ping: {}", ping.value);
55//!
56//!         let data = Pong { value: ping.value };
57//!         pong.write(data).await;
58//!     }
59//! }
60//!
61//! futures::executor::block_on(
62//!     veecle_os_runtime::execute! {
63//!         store: [Ping, Pong],
64//!         actors: [
65//!             PingActor,
66//!             PongActor,
67//!         ]
68//!     }
69//! )
70//! ```
71//!
72//! ## Output
73//!
74//! The expected output for this example would be a sequence of ping/pong messages like the following:
75//!
76//! ```shell
77//! Ping: 1
78//! Pong: 1
79//! Ping: 2
80//! Pong: 2
81//! Ping: 3
82//! Pong: 3
83//! ...
84//! ```
85//!
86//! ## Execution
87//!
88//! See how the `PongActor` waits for `Ping` to be written by the `PingActor`.
89//! If that were not the behavior, we would see `Ping: 0` as the very first output, since `Ping` defaults to zero.
90//! The same would happen with the `PingActor`: if it were not waiting for `Pong` updates, its immediate action after
91//! writing `Ping` would be to display `Pong: 0`. Waiting for updates ensures us that only written values are read.
92//!
93//! On the other hand, writing always yields for other woken futures to be executed before performing the write
94//! operation. The only exception is the very first write, since there is no latest value for readers to read.
95
96#![cfg_attr(docsrs, allow(internal_features))]
97#![cfg_attr(docsrs, feature(rustdoc_internals))]
98#![no_std]
99
100#[cfg(test)]
101extern crate std;
102
103pub(crate) mod actor;
104mod cons;
105pub(crate) mod datastore;
106mod execute;
107
108mod heapfree_executor;
109
110pub mod memory_pool;
111
112pub use self::actor::{Actor, StoreRequest, actor};
113pub use self::datastore::{
114    CombinableReader, CombineReaders, ExclusiveReader, InitializedReader, Reader, Storable, Writer,
115};
116
117/// Internal exports for proc-macro and `macro_rules!` purposes.
118#[doc(hidden)]
119pub mod __exports {
120    pub use crate::actor::{Datastore, IsActorResult};
121    pub use crate::cons::{Cons, Nil, TupleConsToCons};
122    pub use crate::execute::{execute_actor, make_store, validate_actors};
123    pub use crate::heapfree_executor::{Executor, ExecutorShared};
124}