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};
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>::from_millis(1);
22//!     if t.timeout() {
23//!         // handle timeout
24//!     }
25//!
26//!     let (notifier, waiter) = OS::notify();
27//!     assert!(notifier.notify());
28//!     assert!(waiter.wait(&Duration::<OS>::from_millis(1)));
29//! }
30//!
31//! fn select_os() {
32//!     use_os::<FakeOs>();
33//!     use_os::<StdOs>();
34//! }
35//! ```
36//!
37//! Use alias for convenience:
38//! ```
39//! use os_trait::{prelude::*, StdOs as OS, os_type_alias};
40//!
41//! os_type_alias!(OS);
42//!
43//! fn use_os_type() {
44//!     let mutex = Mutex::new(2);
45//!     OS::yield_thread();
46//!     OS::delay().delay_ms(1);
47//!
48//!     let t = Timeout::from_millis(1);
49//!     let dur = Duration::from_millis(1);
50//!
51//!     let (notifier, waiter) = OS::notify();
52//!     assert!(notifier.notify());
53//!     assert!(waiter.wait(&Duration::from_millis(1)));
54//! }
55//! ```
56
57#![cfg_attr(not(feature = "std"), no_std)]
58
59pub mod mutex;
60pub mod notifier;
61pub mod notifier_impls;
62pub mod os_impls;
63pub mod prelude;
64
65pub use fugit;
66pub use mutex::{BlockingMutex, FakeRawMutex};
67pub use mutex_traits;
68pub use mutex_traits::{ConstInit, RawMutex};
69pub use notifier::*;
70pub use notifier_impls::*;
71pub use os_impls::{FakeOs, StdOs};
72pub use timeout_trait::{self, *};
73
74#[cfg(feature = "alloc")]
75extern crate alloc;
76
77/// The interface for different operating systems.
78pub trait OsInterface: Send + Sync + Sized + 'static {
79    type RawMutex: ConstInit + RawMutex;
80    type Notifier: NotifierInterface;
81    type NotifyWaiter: NotifyWaiterInterface<Self>;
82    type Instant: TickInstant;
83    type Delay: DelayNs;
84
85    /// It's used to avoid writing `foo::<OS, _, _, _>(...)`
86    const O: Self;
87
88    fn yield_thread();
89
90    #[inline(always)]
91    fn yield_task() {
92        Self::yield_thread()
93    }
94
95    fn delay() -> Self::Delay;
96    fn notify() -> (Self::Notifier, Self::NotifyWaiter);
97
98    #[inline]
99    fn mutex<T>(d: T) -> Mutex<Self, T> {
100        Mutex::<Self, T>::new(d)
101    }
102}
103
104pub type Mutex<OS, T> = BlockingMutex<<OS as OsInterface>::RawMutex, T>;
105pub type Notifier<OS> = <OS as OsInterface>::Notifier;
106pub type NotifyWaiter<OS> = <OS as OsInterface>::NotifyWaiter;
107pub type Timeout<OS> = TickTimeout<<OS as OsInterface>::Instant>;
108pub type Duration<OS> = TickDuration<<OS as OsInterface>::Instant>;
109
110/// Use this macro to alias the OS-specific types for greater convenience,
111/// or manually alias only the ones you need.
112#[macro_export]
113macro_rules! os_type_alias {
114    ($YOUR_OS:ty) => {
115        pub type Mutex<T> = $crate::Mutex<$YOUR_OS, T>;
116        pub type Notifier = $crate::Notifier<$YOUR_OS>;
117        pub type NotifyWaiter = $crate::NotifyWaiter<$YOUR_OS>;
118        pub type Timeout = $crate::Timeout<$YOUR_OS>;
119        pub type Duration = $crate::Duration<$YOUR_OS>;
120    };
121}