lib.rs 7.4 KB

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