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::fmt::Debug;
17//!
18//! use veecle_os_runtime::{Never, Reader, Storable, Writer};
19//!
20//! #[derive(Debug, Clone, PartialEq, Eq, Default, Storable)]
21//! pub struct Ping {
22//!     value: u32,
23//! }
24//!
25//! #[derive(Debug, Clone, PartialEq, Eq, Default, Storable)]
26//! pub struct Pong {
27//!     value: u32,
28//! }
29//!
30//! #[veecle_os_runtime::actor]
31//! async fn ping_actor(mut ping: Writer<'_, Ping>, pong: Reader<'_, Pong>) -> Never {
32//!     let mut value = 0;
33//!     ping.write(Ping { value }).await;
34//!
35//!     let mut pong = pong.wait_init().await;
36//!     loop {
37//!         ping.write(Ping { value }).await;
38//!         value += 1;
39//!
40//!         pong.wait_for_update().await.read(|pong| {
41//!             println!("Pong: {}", pong.value);
42//!         });
43//! #       // Exit the application to allow doc-tests to complete.
44//! #       std::process::exit(0);
45//!     }
46//! }
47//!
48//! #[veecle_os_runtime::actor]
49//! async fn pong_actor(mut pong: Writer<'_, Pong>, ping: Reader<'_, Ping>) -> Never {
50//!     let mut ping = ping.wait_init().await;
51//!     loop {
52//!         let ping = ping.wait_for_update().await.read_cloned();
53//!         println!("Ping: {}", ping.value);
54//!
55//!         let data = Pong { value: ping.value };
56//!         pong.write(data).await;
57//!     }
58//! }
59//!
60//! futures::executor::block_on(
61//!     veecle_os_runtime::execute! {
62//!         actors: [
63//!             PingActor,
64//!             PongActor,
65//!         ]
66//!     }
67//! )
68//! ```
69//!
70//! ## Output
71//!
72//! The expected output for this example would be a sequence of ping/pong messages like the following:
73//!
74//! ```shell
75//! Ping: 1
76//! Pong: 1
77//! Ping: 2
78//! Pong: 2
79//! Ping: 3
80//! Pong: 3
81//! ...
82//! ```
83//!
84//! ## Execution
85//!
86//! See how the `PongActor` waits for `Ping` to be written by the `PingActor`.
87//! If that were not the behavior, we would see `Ping: 0` as the very first output, since `Ping` defaults to zero.
88//! The same would happen with the `PingActor`: if it were not waiting for `Pong` updates, its immediate action after
89//! writing `Ping` would be to display `Pong: 0`. Waiting for updates ensures us that only written values are read.
90//!
91//! On the other hand, writing always yields for other woken futures to be executed before performing the write
92//! operation. The only exception is the very first write, since there is no latest value for readers to read.
93
94#![cfg_attr(docsrs, allow(internal_features))]
95#![cfg_attr(docsrs, feature(rustdoc_internals))]
96#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
97#![no_std]
98
99#[cfg(test)]
100extern crate std;
101
102pub(crate) mod actor;
103mod cons;
104pub(crate) mod datastore;
105mod execute;
106
107mod heapfree_executor;
108
109pub mod memory_pool;
110
111pub use self::actor::{Actor, StoreRequest, actor};
112pub use self::datastore::{
113    CombinableReader, CombineReaders, ExclusiveReader, InitializedReader, Reader, Storable, Writer,
114};
115
116/// Internal exports for proc-macro and `macro_rules!` purposes.
117#[doc(hidden)]
118pub mod __exports {
119    pub use crate::actor::{Datastore, DefinesSlot, IsActorResult};
120    pub use crate::cons::{AppendCons, Cons, Nil};
121    pub use crate::execute::{execute_actor, make_store_and_validate};
122    pub use crate::heapfree_executor::{Executor, ExecutorShared};
123}
124
125/// A type that can never be constructed.
126///
127/// Used as the success type in `Result<Never, E>` to indicate that an operation
128/// never returns successfully, only by error. This is semantically clearer than
129/// using `Infallible` which suggests "cannot fail."
130///
131// TODO(https://github.com/rust-lang/rust/issues/35121)
132/// This type will be replaced with the never type [`!`] once it is stabilized.
133#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
134pub enum Never {}
135
136impl core::fmt::Display for Never {
137    fn fmt(&self, _: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
138        match *self {}
139    }
140}
141
142impl core::error::Error for Never {}