zephyr/
simpletls.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//! A simple TLS helping tool.
//!
//! Until this crate implements general TLS support, similar to std, this simpletls module can
//! provide a simplified type of thread-local storage.

extern crate alloc;

use alloc::vec::Vec;
use zephyr_sys::{k_current_get, k_thread};

/// A container for simple thread local storage.
///
/// This will maintain a mapping between Zephyr threads and a value of type T.  Entries will have to
/// be added manually, generally when each thread is started.
///
/// Note that T must implement Copy, as it is not safe to retain references to the inner data
/// outside of this api.
///
/// T must also implement Send, since although 'get' always retrieves the current thread's data,
/// `insert` will typically need to move `T` across threads.
pub struct SimpleTls<T: Copy + Send> {
    map: Vec<(usize, T)>,
}

impl<T: Copy + Send> SimpleTls<T> {
    /// Create a new SimpleTls.
    pub const fn new() -> Self {
        Self { map: Vec::new() }
    }

    /// Insert a new association into the SimpleTls.
    ///
    /// If this thread has already been added, the value will be replaced.
    pub fn insert(&mut self, thread: *const k_thread, data: T) {
        let thread = thread as usize;

        match self.map.binary_search_by(|(id, _)| id.cmp(&thread)) {
            Ok(pos) => self.map[pos] = (thread, data), // Replace existing.
            Err(pos) => self.map.insert(pos, (thread, data)),
        }
    }

    /// Lookup the data associated with a given thread.
    pub fn get(&self) -> Option<T> {
        let thread = unsafe { k_current_get() } as usize;

        self.map
            .binary_search_by(|(id, _)| id.cmp(&thread))
            .ok()
            .map(|pos| self.map[pos].1)
    }
}