1use core::{
2 cell::UnsafeCell,
3 fmt,
4 marker::PhantomData,
5 panic::{RefUnwindSafe, UnwindSafe},
6 sync::atomic::AtomicPtr,
7};
8#[cfg(feature = "anytime_poisoning")]
9use core::sync::atomic::{AtomicBool, Ordering::Release};
10
11pub use access::*;
12pub use awaiter::await_result;
13use error::IgnorePoison;
14use queue::awaiter;
15use queue::Callback;
16pub use queue::editor;
17use queue::state;
18
19type NotSendOrSync = PhantomData<*const ()>;
20
21pub struct Rusturn<T> {
22 queue: AtomicPtr<Callback>,
23 value: UnsafeCell<Option<T>>,
24
25 #[cfg(feature = "anytime_poisoning")]
26 poisoned: AtomicBool,
27}
28
29unsafe impl<T: Send> Sync for Rusturn<T> {}
30unsafe impl<T: Send> Send for Rusturn<T> {}
31
32impl<T> RefUnwindSafe for Rusturn<T> {}
33impl<T> UnwindSafe for Rusturn<T> {}
34
35impl<T> Default for Rusturn<T> {
36 #[inline]
37 fn default() -> Self {
38 Self::new()
39 }
40}
41
42impl<T> From<T> for Rusturn<T> {
43 #[inline]
44 fn from(value: T) -> Self {
45 Self::with_value(value)
46 }
47}
48
49impl<T> Rusturn<T> {
50 #[must_use]
51 #[inline]
52 pub const fn new() -> Self {
53 Self {
54 queue: AtomicPtr::new(state::NONE_PTR),
55 value: UnsafeCell::new(None),
56
57 #[cfg(feature = "anytime_poisoning")]
58 poisoned: AtomicBool::new(false),
59 }
60 }
61
62 #[must_use]
63 #[inline]
64 pub const fn with_value(value: T) -> Self {
65 Self {
66 queue: AtomicPtr::new(state::DONE_PTR),
67 value: UnsafeCell::new(Some(value)),
68
69 #[cfg(feature = "anytime_poisoning")]
70 poisoned: AtomicBool::new(false),
71 }
72 }
73
74 #[cfg(feature = "anytime_poisoning")]
88 #[inline]
89 pub unsafe fn mark_poisoned(&self) {
90 self.poisoned.store(true, Release);
92 match self.try_edit().ignore_poison() {
97 Ok(editor) => editor.action().nothing(),
98 Err(error::InstantAccessError::WouldBlock) => {}
99 }
100 }
101
102 #[inline]
103 pub fn try_edit(&self) -> error::TryEditorAccessResult<'_, T, error::InstantAccessError> {
104 editor::Editor::try_edit(self)
105 }
106}
107
108impl<T> Rusturn<T> {
109 #[must_use]
110 #[inline(always)]
111 pub const fn instant_access(&self) -> Access<&Self, Instantly> {
112 Access::create(self)
113 }
114
115 #[must_use]
116 #[inline(always)]
117 pub const fn blocking_access(&self) -> Access<&Self, Blocking> {
118 Access::create(self)
119 }
120
121 #[must_use]
122 #[inline(always)]
123 pub const fn suspending_access(&self) -> Access<&Self, Suspending> {
124 Access::create(self)
125 }
126}
127
128impl<T: fmt::Debug> fmt::Debug for Rusturn<T> {
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 let mut d = f.debug_struct("Rusturn");
131 let _ = match self.try_edit().ignore_poison() {
132 Ok(editor) => d.field("value", &editor),
133 Err(error::InstantAccessError::WouldBlock) => d.field("value", &format_args!("<busy>")),
134 };
135 d.finish_non_exhaustive()
136 }
137}
138
139mod access;
140pub mod error;
141mod queue;