os_trait/
lib.rs

1//! Traits used to adapter different embedded RTOS.
2//! It defines a trait [`OsInterface`].
3//!
4//! We use the [`mutex-traits`](https://crates.io/crates/mutex-traits) crate to provide mutex functionality.
5//! You can implement your own mutex by implementing the `RawMutex` trait from the `mutex-traits` crate.
6//!
7//! # Example
8//!
9//! ```
10//! use os_trait::{prelude::*, FakeOs, StdOs, Duration, Timeout, Instant};
11//!
12//! fn use_os<OS: OsInterface>() {
13//!     let mutex = OS::mutex(2);
14//!
15//!     let mut guard = mutex.try_lock().unwrap();
16//!     assert_eq!(*guard, 2);
17//!
18//!     OS::yield_thread();
19//!     OS::delay().delay_ms(1);
20//!
21//!     let mut t = Timeout::<OS>::millis(1);
22//!     if t.timeout() {
23//!         // handle timeout
24//!     }
25//!
26//!     let mut now = Instant::<OS>::now();
27//!     now.elapsed();
28//!     if now.timeout(&Duration::<OS>::millis(1)) {}
29//!
30//!     let (notifier, waiter) = OS::notify();
31//!     assert!(notifier.notify());
32//!     assert!(waiter.wait(&Duration::<OS>::millis(1)));
33//! }
34//!
35//! fn select_os() {
36//!     use_os::<FakeOs>();
37//!     use_os::<StdOs>();
38//! }
39//! ```
40//!
41//! Use alias for convenience:
42//! ```
43//! use os_trait::{prelude::*, StdOs as OS, os_type_alias};
44//!
45//! os_type_alias!(OS);
46//!
47//! fn use_os_type() {
48//!     let mutex = Mutex::new(2);
49//!     OS::yield_thread();
50//!     OS::delay().delay_ms(1);
51//!
52//!     let t = Timeout::millis(1);
53//!     let dur = Duration::millis(1);
54//!     let mut now = Instant::now();
55//!     if now.timeout(&dur) {}
56//!
57//!     let (notifier, waiter) = OS::notify();
58//!     assert!(notifier.notify());
59//!     assert!(waiter.wait(&Duration::millis(1)));
60//! }
61//! ```
62
63#![cfg_attr(not(feature = "std"), no_std)]
64
65pub mod mutex;
66pub mod notifier;
67pub mod notifier_impls;
68pub mod os_impls;
69pub mod prelude;
70
71pub use fugit;
72pub use mutex::{BlockingMutex, FakeRawMutex};
73pub use mutex_traits;
74pub use mutex_traits::{ConstInit, RawMutex};
75pub use notifier::*;
76pub use notifier_impls::*;
77pub use os_impls::{FakeOs, StdOs};
78pub use portable_atomic;
79pub use timeout_trait::{self, *};
80
81#[cfg(feature = "alloc")]
82extern crate alloc;
83
84/// The interface for different operating systems.
85pub trait OsInterface: Send + Sync + Sized + 'static {
86    type RawMutex: ConstInit + RawMutex;
87    type Notifier: NotifierInterface;
88    type NotifyWaiter: NotifyWaiterInterface<Self>;
89    type Instant: TickInstant;
90    type Delay: DelayNs;
91
92    /// It's used to avoid writing `foo::<OS, _, _, _>(...)`
93    const O: Self;
94
95    fn yield_thread();
96
97    #[inline(always)]
98    fn yield_task() {
99        Self::yield_thread()
100    }
101
102    fn delay() -> Self::Delay;
103    fn notify() -> (Self::Notifier, Self::NotifyWaiter);
104
105    #[inline]
106    fn mutex<T>(d: T) -> Mutex<Self, T> {
107        Mutex::<Self, T>::new(d)
108    }
109}
110
111pub type Mutex<OS, T> = BlockingMutex<<OS as OsInterface>::RawMutex, T>;
112pub type Notifier<OS> = <OS as OsInterface>::Notifier;
113pub type NotifyWaiter<OS> = <OS as OsInterface>::NotifyWaiter;
114pub type Instant<OS> = <OS as OsInterface>::Instant;
115pub type Duration<OS> = TickDuration<Instant<OS>>;
116pub type Timeout<OS> = TickTimeout<Instant<OS>>;
117pub type Delay<OS> = <OS as OsInterface>::Delay;
118
119/// Use this macro to alias the OS-specific types for greater convenience,
120/// or manually alias only the ones you need.
121#[macro_export]
122macro_rules! os_type_alias {
123    ($YOUR_OS:ty) => {
124        pub type Mutex<T> = $crate::Mutex<$YOUR_OS, T>;
125        pub type Notifier = $crate::Notifier<$YOUR_OS>;
126        pub type NotifyWaiter = $crate::NotifyWaiter<$YOUR_OS>;
127        pub type Instant = $crate::Instant<$YOUR_OS>;
128        pub type Duration = $crate::Duration<$YOUR_OS>;
129        pub type Timeout = $crate::Timeout<$YOUR_OS>;
130        pub type Delay = $crate::Delay<$YOUR_OS>;
131    };
132}