1use core::sync::atomic::Ordering::SeqCst;
7use core::sync::atomic::AtomicPtr;
8
9use alloc::boxed::Box;
10
11use crate::try_swap_ptr;
12
13pub struct Slot<T> {
15 inner: AtomicPtr<T>,
16}
17
18impl<T> Slot<T> {
19 const EMPTY: *mut T = 1 as *mut T;
20 const LOCKED: *mut T = 2 as *mut T;
21
22 pub const NONE: Self = Self {
23 inner: AtomicPtr::new(Self::EMPTY)
24 };
25
26 pub fn new(item: Box<T>) -> Self {
30 let slot = Self::default();
31 assert!(slot.try_insert(item).is_ok());
32 slot
33 }
34
35 pub fn try_insert(&self, item: Box<T>) -> Result<(), Box<T>> {
37 let item_ptr = Box::leak(item);
38 match try_swap_ptr(&self.inner, Self::EMPTY, item_ptr) {
39 true => Ok(()),
40 false => Err(unsafe { Box::from_raw(item_ptr) }),
41 }
42 }
43
44 pub fn insert(&self, item: Box<T>) -> Option<Box<T>> {
48 let item_ptr = Box::leak(item);
49 match self.inner.swap(item_ptr, SeqCst) {
50 p if p == (Self::EMPTY) || (p == Self::LOCKED) => None,
51 other => Some(unsafe { Box::from_raw(other) }),
52 }
53 }
54
55 pub fn try_take(&self, lock: bool) -> Option<Box<T>> {
59 let item_ptr = match self.inner.load(SeqCst) {
60 p if p == (Self::EMPTY) || (p == Self::LOCKED) => None,
61 other => Some(other),
62 }?;
63
64 let next = match lock {
65 true => Self::LOCKED,
66 false => Self::EMPTY,
67 };
68
69 match try_swap_ptr(&self.inner, item_ptr, next) {
70 true => Some(unsafe { Box::from_raw(item_ptr) }),
71 false => None,
72 }
73 }
74
75 pub fn is_locked(&self) -> bool {
76 self.inner.load(SeqCst) == Self::LOCKED
77 }
78
79 pub fn unlock(&self) -> bool {
83 try_swap_ptr(&self.inner, Self::LOCKED, Self::EMPTY)
84 }
85}
86
87impl<T> Default for Slot<T> {
88 fn default() -> Self {
89 Self::NONE
90 }
91}
92
93impl<T> Drop for Slot<T> {
94 fn drop(&mut self) {
95 core::mem::drop(self.try_take(true));
96 }
97}