lib.rs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. //! The code is based on https://github.com/matklad/once_cell
  2. #![no_std]
  3. use core::{
  4. cell::UnsafeCell,
  5. fmt,
  6. mem::MaybeUninit,
  7. ptr,
  8. sync::atomic::{AtomicU8, Ordering},
  9. };
  10. // Why do we need `T: Send`?
  11. // Thread A creates a `OnceCell` and shares it with
  12. // scoped thread B, which fills the cell, which is
  13. // then destroyed by A. That is, destructor observes
  14. // a sent value.
  15. unsafe impl<T: Sync + Send> Sync for OnceCell<T> {}
  16. unsafe impl<T: Send> Send for OnceCell<T> {}
  17. // Three states that a OnceCell can be in, encoded into the lower bits of `state` in
  18. // the OnceCell structure.
  19. const INCOMPLETE: u8 = 0x0;
  20. const RUNNING: u8 = 0x1;
  21. const COMPLETE: u8 = 0x2;
  22. /// A cell which can be written to only once.
  23. ///
  24. /// Unlike `:td::cell::RefCell`, a `OnceCell` provides simple `&`
  25. /// references to the contents.
  26. ///
  27. /// # Example
  28. /// ```
  29. /// use nostd_cell::OnceCell;
  30. ///
  31. /// let cell = OnceCell::new();
  32. /// assert!(cell.get().is_none());
  33. ///
  34. /// let value: &String = cell.get_or_init(|| {
  35. /// "Hello, World!".to_string()
  36. /// });
  37. /// assert_eq!(value, "Hello, World!");
  38. /// assert!(cell.get().is_some());
  39. /// ```
  40. pub struct OnceCell<T> {
  41. inner: UnsafeCell<MaybeUninit<T>>,
  42. state: AtomicU8,
  43. }
  44. impl<T> Default for OnceCell<T> {
  45. fn default() -> Self {
  46. Self::new()
  47. }
  48. }
  49. impl<T: fmt::Debug> fmt::Debug for OnceCell<T> {
  50. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  51. match self.get() {
  52. Some(v) => f.debug_tuple("OnceCell").field(v).finish(),
  53. None => f.write_str("OnceCell(Uninit)"),
  54. }
  55. }
  56. }
  57. impl<T: Clone> Clone for OnceCell<T> {
  58. fn clone(&self) -> OnceCell<T> {
  59. let res = OnceCell::new();
  60. if let Some(value) = self.get() {
  61. match res.set(value.clone()) {
  62. Ok(()) => (),
  63. Err(_) => unreachable!(),
  64. }
  65. }
  66. res
  67. }
  68. }
  69. impl<T: PartialEq> PartialEq for OnceCell<T> {
  70. fn eq(&self, other: &Self) -> bool {
  71. self.get() == other.get()
  72. }
  73. }
  74. impl<T: Eq> Eq for OnceCell<T> {}
  75. impl<T> From<T> for OnceCell<T> {
  76. fn from(value: T) -> Self {
  77. OnceCell {
  78. inner: UnsafeCell::new(MaybeUninit::new(value)),
  79. state: AtomicU8::new(COMPLETE),
  80. }
  81. }
  82. }
  83. impl<T> OnceCell<T> {
  84. /// Creates a new empty cell.
  85. pub const fn new() -> OnceCell<T> {
  86. OnceCell {
  87. inner: UnsafeCell::new(MaybeUninit::uninit()),
  88. state: AtomicU8::new(INCOMPLETE),
  89. }
  90. }
  91. /// Gets the reference to the underlying value.
  92. ///
  93. /// Returns `None` if the cell is empty.
  94. pub fn get(&self) -> Option<&T> {
  95. if self.is_complete_acquire() {
  96. Some(self.get_unsafe())
  97. } else {
  98. None
  99. }
  100. }
  101. /// Gets the mutable reference to the underlying value.
  102. ///
  103. /// Returns `None` if the cell is empty.
  104. pub fn get_mut(&mut self) -> Option<&mut T> {
  105. if self.is_complete_acquire() {
  106. Some(unsafe { &mut *(*self.inner.get()).as_mut_ptr() })
  107. } else {
  108. None
  109. }
  110. }
  111. fn is_complete_acquire(&self) -> bool {
  112. self.state.load(Ordering::Acquire) == COMPLETE
  113. }
  114. fn get_unsafe(&self) -> &T {
  115. unsafe { &*(*self.inner.get()).as_ptr() }
  116. }
  117. fn set_unsafe(&self, value: T) {
  118. unsafe {
  119. ptr::write((*self.inner.get()).as_mut_ptr(), value);
  120. self.state.store(COMPLETE, Ordering::Release);
  121. }
  122. }
  123. /// Sets the contents of this cell to `value`.
  124. ///
  125. /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was
  126. /// full.
  127. ///
  128. /// # Example
  129. /// ```
  130. /// use nostd_cell::OnceCell;
  131. ///
  132. /// let cell = OnceCell::new();
  133. /// assert!(cell.get().is_none());
  134. ///
  135. /// assert_eq!(cell.set(92), Ok(()));
  136. /// assert_eq!(cell.set(62), Err(62));
  137. ///
  138. /// assert!(cell.get().is_some());
  139. /// ```
  140. pub fn set(&self, value: T) -> Result<(), T> {
  141. let state = self
  142. .state
  143. .compare_and_swap(INCOMPLETE, RUNNING, Ordering::AcqRel);
  144. if state == INCOMPLETE {
  145. self.set_unsafe(value);
  146. } else {
  147. return Err(value);
  148. }
  149. Ok(())
  150. }
  151. /// Gets the contents of the cell, initializing it with `f`
  152. /// if the cell was empty.
  153. ///
  154. /// # Panics
  155. ///
  156. /// If `f` panics, the panic is propagated to the caller, and the cell
  157. /// remains uninitialized.
  158. ///
  159. /// It is an error to reentrantly initialize the cell from `f`. Doing
  160. /// so results in a panic.
  161. ///
  162. /// # Example
  163. /// ```
  164. /// use nostd_cell::OnceCell;
  165. ///
  166. /// let cell = OnceCell::new();
  167. /// let value = cell.get_or_init(|| 92);
  168. /// assert_eq!(value, &92);
  169. /// let value = cell.get_or_init(|| unreachable!());
  170. /// assert_eq!(value, &92);
  171. /// ```
  172. pub fn get_or_init<F>(&self, f: F) -> &T
  173. where
  174. F: FnOnce() -> T,
  175. {
  176. enum Void {}
  177. match self.get_or_try_init(|| Ok::<T, Void>(f())) {
  178. Ok(val) => val,
  179. Err(void) => match void {},
  180. }
  181. }
  182. /// Gets the contents of the cell, initializing it with `f` if
  183. /// the cell was empty. If the cell was empty and `f` failed, an
  184. /// error is returned.
  185. ///
  186. /// # Panics
  187. ///
  188. /// If `f` panics, the panic is propagated to the caller, and the cell
  189. /// remains uninitialized.
  190. ///
  191. /// It is an error to reentrantly initialize the cell from `f`. Doing
  192. /// so results in a panic.
  193. ///
  194. /// # Example
  195. /// ```
  196. /// use nostd_cell::OnceCell;
  197. ///
  198. /// let cell = OnceCell::new();
  199. /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
  200. /// assert!(cell.get().is_none());
  201. /// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
  202. /// Ok(92)
  203. /// });
  204. /// assert_eq!(value, Ok(&92));
  205. /// assert_eq!(cell.get(), Some(&92))
  206. /// ```
  207. pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
  208. where
  209. F: FnOnce() -> Result<T, E>,
  210. {
  211. let state = self
  212. .state
  213. .compare_and_swap(INCOMPLETE, RUNNING, Ordering::AcqRel);
  214. match state {
  215. COMPLETE => {
  216. return Ok(self.get_unsafe());
  217. }
  218. INCOMPLETE => {
  219. // In case f() panics, OnceCell will be permanently empty (in RUNNING state).
  220. match f() {
  221. Ok(value) => {
  222. self.set_unsafe(value);
  223. return Ok(self.get_unsafe());
  224. }
  225. Err(err) => {
  226. self.state.store(INCOMPLETE, Ordering::Release);
  227. return Err(err);
  228. }
  229. }
  230. }
  231. _ => {
  232. // It would be great to return error here, but API doesn't allow it.
  233. panic!("reentrant init");
  234. }
  235. }
  236. }
  237. /// Consumes the `OnceCell`, returning the wrapped value.
  238. ///
  239. /// Returns `None` if the cell was empty.
  240. ///
  241. /// # Examples
  242. ///
  243. /// ```
  244. /// use nostd_cell::OnceCell;
  245. ///
  246. /// let cell: OnceCell<String> = OnceCell::new();
  247. /// assert_eq!(cell.into_inner(), None);
  248. ///
  249. /// let cell = OnceCell::new();
  250. /// cell.set("hello".to_string()).unwrap();
  251. /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
  252. /// ```
  253. pub fn into_inner(self) -> Option<T> {
  254. // Because `into_inner` takes `self` by value, the compiler statically verifies
  255. // that it is not currently borrowed. So it is safe to move out `Option<T>`.
  256. if self.is_complete_acquire() {
  257. Some(unsafe { self.inner.into_inner().assume_init() })
  258. } else {
  259. None
  260. }
  261. }
  262. }