zephyr/
simpletls.rs

1//! A simple TLS helping tool.
2//!
3//! Until this crate implements general TLS support, similar to std, this simpletls module can
4//! provide a simplified type of thread-local storage.
5
6extern crate alloc;
7
8use alloc::vec::Vec;
9use zephyr_sys::{k_current_get, k_thread};
10
11/// A container for simple thread local storage.
12///
13/// This will maintain a mapping between Zephyr threads and a value of type T.  Entries will have to
14/// be added manually, generally when each thread is started.
15///
16/// Note that T must implement Copy, as it is not safe to retain references to the inner data
17/// outside of this api.
18///
19/// T must also implement Send, since although 'get' always retrieves the current thread's data,
20/// `insert` will typically need to move `T` across threads.
21pub struct SimpleTls<T: Copy + Send> {
22    map: Vec<(usize, T)>,
23}
24
25impl<T: Copy + Send> SimpleTls<T> {
26    /// Create a new SimpleTls.
27    pub const fn new() -> Self {
28        Self { map: Vec::new() }
29    }
30
31    /// Insert a new association into the SimpleTls.
32    ///
33    /// If this thread has already been added, the value will be replaced.
34    pub fn insert(&mut self, thread: *const k_thread, data: T) {
35        let thread = thread as usize;
36
37        match self.map.binary_search_by(|(id, _)| id.cmp(&thread)) {
38            Ok(pos) => self.map[pos] = (thread, data), // Replace existing.
39            Err(pos) => self.map.insert(pos, (thread, data)),
40        }
41    }
42
43    /// Lookup the data associated with a given thread.
44    pub fn get(&self) -> Option<T> {
45        let thread = unsafe { k_current_get() } as usize;
46
47        self.map
48            .binary_search_by(|(id, _)| id.cmp(&thread))
49            .ok()
50            .map(|pos| self.map[pos].1)
51    }
52}