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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use super::common::MemorySeek;
use atomic::Atomic;
use core::mem::MaybeUninit;
use core::ops::Deref;
use core::ptr;
use core::sync::atomic::{AtomicBool, Ordering::Relaxed};
pub struct Seek<'a, T>(&'a AtomicOption<T>);
impl<'a, T> Seek<'a, T> {
pub fn remove(&self) {
self.0.will_drop.store(true, Relaxed);
}
}
impl<'a, T> Deref for Seek<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { self.0.val.assume_init_ref() }
}
}
impl<'a, T> Drop for Seek<'a, T> {
fn drop(&mut self) {
let will_drop = self.0.will_drop.load(Relaxed);
let old = self.0.state.fetch_update(Relaxed, Relaxed, |mut x| {
if x == MemorySeek::SEEK1 {
if will_drop {
return Some(MemorySeek::READING);
}
}
if x.seek_sub().is_ok() {
Some(x)
} else {
None
}
});
match old {
Ok(MemorySeek::SEEK1) => {
if will_drop {
unsafe { ptr::drop_in_place(self.0.val.as_ptr() as *mut T) };
self.0.will_drop.store(false, Relaxed);
self.0.state.store(MemorySeek::UNINITIALIZED, Relaxed);
}
}
_ => {}
}
}
}
#[derive(Debug)]
pub struct AtomicOption<T> {
val: MaybeUninit<T>,
state: Atomic<MemorySeek>,
will_drop: AtomicBool,
}
impl<T> AtomicOption<T> {
pub const fn new() -> Self {
AtomicOption {
val: MaybeUninit::uninit(),
state: Atomic::new(MemorySeek::UNINITIALIZED),
will_drop: AtomicBool::new(false),
}
}
fn ptr(&self) -> *mut T {
self.val.as_ptr() as *mut T
}
pub fn is_some(&self) -> bool {
let state = self.state.load(Relaxed);
state.can_seek()
}
pub fn is_none(&self) -> bool {
self.state.load(Relaxed) == MemorySeek::UNINITIALIZED
}
pub fn take(&self) -> Option<T> {
if let Err(_) = self.state.fetch_update(Relaxed, Relaxed, |x| match x {
MemorySeek::WRITTEN => Some(MemorySeek::READING),
_ => None,
}) {
None
} else {
let ret = Some(unsafe { ptr::read(self.ptr()) });
self.state.store(MemorySeek::UNINITIALIZED, Relaxed);
ret
}
}
pub fn seek(&self) -> Result<Seek<T>, MemorySeek> {
if let Err(x) = self.state.fetch_update(Relaxed, Relaxed, |mut x| {
if x.can_seek() {
let _ = x.seek_add();
Some(x)
} else {
None
}
}) {
Err(x)
} else {
Ok(Seek(self))
}
}
pub fn push(&self, value: T) -> Result<(), T> {
if let Err(_) = self.state.compare_exchange(
MemorySeek::UNINITIALIZED,
MemorySeek::WRITTING,
Relaxed,
Relaxed,
) {
Err(value)
} else {
unsafe { ptr::write(self.ptr(), value) };
self.state.store(MemorySeek::WRITTEN, Relaxed);
Ok(())
}
}
}
impl<T> Drop for AtomicOption<T> {
fn drop(&mut self) {
self.take();
}
}