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
119
120
121
122
123
124
125
126
127
128
use super::common::MemorySeek;
use atomic::Atomic;
use core::fmt;
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: fmt::Debug> fmt::Debug for Seek<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self, f)
}
}
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);
}
}
_ => {}
}
}
}
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: fmt::Debug> fmt::Debug for AtomicOption<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.seek(), f)
}
}
impl<T> Drop for AtomicOption<T> {
fn drop(&mut self) {
self.take();
}
}