rtic_core/
lib.rs

1//! Core abstractions of the Real-Time Interrupt-driven Concurrency (RTIC) framework
2//!
3//! You can write generic *libraries* using the `Mutex` trait in this crate. If you want to write
4//! application code then you'll need an *implementation* of the RTIC framework for a particular
5//! architecture. Currently, there are implementations for these architectures and OSes:
6//!
7//! - [ARM Cortex-M](https://crates.io/crates/cortex-m-rtic)
8// - [Linux]
9// - [MSP430]
10// - [RISC-V]
11
12#![deny(missing_docs)]
13#![deny(rust_2021_compatibility)]
14#![deny(rust_2018_compatibility)]
15#![deny(rust_2018_idioms)]
16#![no_std]
17#![doc(
18    html_logo_url = "https://raw.githubusercontent.com/rtic-rs/cortex-m-rtic/master/book/en/src/RTIC.svg",
19    html_favicon_url = "https://raw.githubusercontent.com/rtic-rs/cortex-m-rtic/master/book/en/src/RTIC.svg"
20)]
21//deny_warnings_placeholder_for_ci
22
23use core::ops;
24
25/// Memory safe access to shared resources
26///
27/// In RTIC, locks are implemented as critical sections that prevent other tasks from *starting*.
28/// These critical sections are implemented by temporarily increasing the dynamic priority of the
29/// current context. Entering and leaving these critical sections is always done in bounded constant
30/// time (a few instructions in bare metal contexts).
31pub trait Mutex {
32    /// Data protected by the mutex
33    type T;
34
35    /// Creates a critical section and grants temporary access to the protected data
36    fn lock<R>(&mut self, f: impl FnOnce(&mut Self::T) -> R) -> R;
37}
38
39impl<'a, M> Mutex for &'a mut M
40where
41    M: Mutex,
42{
43    type T = M::T;
44
45    fn lock<R>(&mut self, f: impl FnOnce(&mut M::T) -> R) -> R {
46        M::lock(self, f)
47    }
48}
49
50/// Newtype over `&'a mut T` that implements the `Mutex` trait
51///
52/// The `Mutex` implementation for this type is a no-op: no critical section is created
53pub struct Exclusive<'a, T>(pub &'a mut T);
54
55impl<'a, T> Mutex for Exclusive<'a, T> {
56    type T = T;
57
58    fn lock<R>(&mut self, f: impl FnOnce(&mut T) -> R) -> R {
59        f(self.0)
60    }
61}
62
63impl<'a, T> ops::Deref for Exclusive<'a, T> {
64    type Target = T;
65
66    fn deref(&self) -> &T {
67        self.0
68    }
69}
70
71impl<'a, T> ops::DerefMut for Exclusive<'a, T> {
72    fn deref_mut(&mut self) -> &mut T {
73        self.0
74    }
75}
76
77/// Makes locks work on N-tuples, locks the mutexes from left-to-right in the tuple. These are
78/// used to reduce rightward drift in code and to help make intentions clearer.
79///
80/// # Example
81///
82/// ```
83/// use rtic_core::prelude::*;
84///
85/// fn normal_lock(
86///     a: &mut impl Mutex<T = i32>,
87///     b: &mut impl Mutex<T = i32>,
88///     c: &mut impl Mutex<T = i32>
89/// ) {
90///     // A lot of rightward drift...
91///     a.lock(|a| {
92///         b.lock(|b| {
93///             c.lock(|c| {
94///                 *a += 1;
95///                 *b += 1;
96///                 *c += 1;
97///             });
98///         });
99///     });
100/// }
101/// ```
102///
103/// Has a shorthand as:
104///
105/// ```
106/// use rtic_core::prelude::*;
107///
108/// fn tuple_lock(
109///     a: &mut impl Mutex<T = i32>,
110///     b: &mut impl Mutex<T = i32>,
111///     c: &mut impl Mutex<T = i32>
112/// ) {
113///     // Look! Single indent and less to write
114///     (a, b, c).lock(|a, b, c| {
115///         *a += 1;
116///         *b += 1;
117///         *c += 1;
118///     });
119/// }
120/// ```
121pub mod prelude {
122    pub use crate::Mutex;
123
124    macro_rules! lock {
125        ($e:ident, $fun:block) => {
126            $e.lock(|$e| $fun )
127        };
128        ($e:ident, $($es:ident),+, $fun:block) => {
129            $e.lock(|$e| lock!($($es),*, $fun))
130        };
131    }
132
133    macro_rules! make_tuple_impl {
134        ($name:ident, $($es:ident),+) => {
135            /// Auto-generated tuple implementation, see [`Mutex`](../trait.Mutex.html) for details.
136            pub trait $name {
137                $(
138                    /// Data protected by the mutex.
139                    type $es;
140                )*
141
142                /// Creates a critical section and grants temporary access to the protected data.
143                fn lock<R>(&mut self, f: impl FnOnce($(&mut Self::$es),*) -> R) -> R;
144            }
145
146            impl<$($es),+> $name for ($($es,)+)
147            where
148                $($es: crate::Mutex),*
149            {
150                $(
151                    type $es = $es::T;
152                )*
153
154                #[allow(non_snake_case)]
155                fn lock<R>(&mut self, f: impl FnOnce($(&mut Self::$es),*) -> R) -> R {
156                    let ($(
157                        $es,
158                    )*) = self;
159
160                    lock!($($es),*, { f($($es),*) })
161                }
162            }
163        };
164    }
165
166    // Generate tuple lock impls
167    make_tuple_impl!(TupleExt01, T1);
168    make_tuple_impl!(TupleExt02, T1, T2);
169    make_tuple_impl!(TupleExt03, T1, T2, T3);
170    make_tuple_impl!(TupleExt04, T1, T2, T3, T4);
171    make_tuple_impl!(TupleExt05, T1, T2, T3, T4, T5);
172    make_tuple_impl!(TupleExt06, T1, T2, T3, T4, T5, T6);
173    make_tuple_impl!(TupleExt07, T1, T2, T3, T4, T5, T6, T7);
174    make_tuple_impl!(TupleExt08, T1, T2, T3, T4, T5, T6, T7, T8);
175    make_tuple_impl!(TupleExt09, T1, T2, T3, T4, T5, T6, T7, T8, T9);
176    make_tuple_impl!(TupleExt10, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
177    make_tuple_impl!(TupleExt11, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
178    make_tuple_impl!(TupleExt12, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
179    make_tuple_impl!(TupleExt13, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
180    make_tuple_impl!(TupleExt14, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
181    make_tuple_impl!(TupleExt15, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
182    make_tuple_impl!(
183        TupleExt16, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16
184    );
185    make_tuple_impl!(
186        TupleExt17, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17
187    );
188    make_tuple_impl!(
189        TupleExt18, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18
190    );
191    make_tuple_impl!(
192        TupleExt19, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
193        T18, T19
194    );
195    make_tuple_impl!(
196        TupleExt20, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
197        T18, T19, T20
198    );
199    make_tuple_impl!(
200        TupleExt21, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
201        T18, T19, T20, T21
202    );
203    make_tuple_impl!(
204        TupleExt22, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
205        T18, T19, T20, T21, T22
206    );
207    make_tuple_impl!(
208        TupleExt23, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
209        T18, T19, T20, T21, T22, T23
210    );
211    make_tuple_impl!(
212        TupleExt24, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
213        T18, T19, T20, T21, T22, T23, T24
214    );
215    make_tuple_impl!(
216        TupleExt25, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
217        T18, T19, T20, T21, T22, T23, T24, T25
218    );
219    make_tuple_impl!(
220        TupleExt26, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
221        T18, T19, T20, T21, T22, T23, T24, T25, T26
222    );
223    make_tuple_impl!(
224        TupleExt27, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
225        T18, T19, T20, T21, T22, T23, T24, T25, T26, T27
226    );
227    make_tuple_impl!(
228        TupleExt28, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
229        T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28
230    );
231    make_tuple_impl!(
232        TupleExt29, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
233        T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29
234    );
235    make_tuple_impl!(
236        TupleExt30, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
237        T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30
238    );
239    make_tuple_impl!(
240        TupleExt31, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
241        T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31
242    );
243    make_tuple_impl!(
244        TupleExt32, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17,
245        T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32
246    );
247}