sel4_one_ref_cell/
lib.rs

1//
2// Copyright 2023, Colias Group, LLC
3//
4// SPDX-License-Identifier: BSD-2-Clause
5//
6
7#![no_std]
8
9use core::cell::UnsafeCell;
10use core::sync::atomic::{AtomicBool, Ordering};
11
12pub struct OneRefCell<T> {
13    taken: AtomicBool,
14    value: UnsafeCell<T>,
15}
16
17unsafe impl<T> Sync for OneRefCell<T> {}
18
19impl<T: Default> Default for OneRefCell<T> {
20    fn default() -> Self {
21        Self::new(Default::default())
22    }
23}
24
25impl<T> From<T> for OneRefCell<T> {
26    fn from(t: T) -> Self {
27        Self::new(t)
28    }
29}
30
31impl<T> OneRefCell<T> {
32    pub const fn new(value: T) -> Self {
33        Self {
34            taken: AtomicBool::new(false),
35            value: UnsafeCell::new(value),
36        }
37    }
38
39    pub fn take(&self) -> Result<&mut T, Error> {
40        if self.taken.swap(true, Ordering::SeqCst) {
41            Err(Error::AlreadyTaken)
42        } else {
43            let ptr = self.value.get();
44            Ok(unsafe { ptr.as_mut() }.unwrap())
45        }
46    }
47}
48
49#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
50pub enum Error {
51    AlreadyTaken,
52}