takecell/
lib.rs

1//! This crate provides two new cell-like types, `TakeCell` and `TakeOwnCell`.
2//! Both may store arbitrary non-`Copy` types, can be read from at most once and
3//! provide direct unique access to the stored contents. The core API looks
4//! roughly like this (and there’s much more inside, read on!):
5//! ```rust,ignore
6//! impl<T> TakeCell<T> {
7//!     const fn new(v: T) -> Self { ... }
8//! }
9//! impl<T: ?Sized> TakeCell<T> {
10//!     fn take(&self) -> Option<&mut T> { ... }
11//! }
12//!
13//! impl<T> TakeOwnCell<T> {
14//!     const fn new(v: T) -> Self { ... }
15//!     fn take(&self) -> Option<T> { ... }
16//! }
17//! ```
18//! Note that, like with `RefCell` and `Mutex`, the `take` method requires only
19//! a shared reference. Because of the single read restriction `take` can
20//! return a `&mut T` or `T` instead of `RefMut<T>` or `MutexGuard<T>`. In some
21//! sense `TakeCell` can be thought as a `Mutex` without unlocking (or rather
22//! with unlocking requiring unique access to the `Mutex`, see [`heal`]).
23//!
24//! [`heal`]: TakeCell::heal
25//!
26//! This crate is `#![no_std]` and only requires little sychronization via 8-bit
27//! atomic.
28//!
29//! ## Usage examples
30//!
31//! ### Singletons
32//!
33//! `TakeCell` is `Sync` (when `T: Sync`) and as such it may be used in
34//! `static`s. This can be used to create singletons:
35//!
36//! ```
37//! use takecell::TakeCell;
38//!
39//! #[non_exhaustive]
40//! pub struct Peripherals {
41//!     pub something: Something,
42//! }
43//!
44//! pub static PEREPHERALS: TakeCell<Peripherals> = TakeCell::new(Peripherals {
45//!     something: Something,
46//! });
47//! # pub struct Something;
48//!
49//! let peripherals: &'static mut _ = PEREPHERALS.take().unwrap();
50//! ```
51//!
52//! ### Doing work only once
53//!
54//! ```
55//! use once_cell::sync::OnceCell;
56//! use std::sync::{Arc, Condvar, Mutex};
57//! use takecell::TakeCell;
58//!
59//! #[derive(Clone)]
60//! struct Job {
61//!     // Input can be a type which requires unique access to be used (e.g.: `dyn Read`)
62//!     input: Arc<TakeCell<Input>>,
63//!     output: Arc<OnceCell<Output>>,
64//!     wait: Arc<(Mutex<bool>, Condvar)>,
65//! }
66//!
67//! fn execute(job: Job) -> Output {
68//!     match job.input.take() {
69//!         Some(input) => {
70//!             // Nobody has started executing the job yet, so execute it
71//!             let output = input.process();
72//!
73//!             // Write the output
74//!             job.output.set(output);
75//!
76//!             // Notify other threads that the job is done
77//!             let (lock, cvar) = &*job.wait;
78//!             let mut done = lock.lock().unwrap();
79//!             *done = true;
80//!         }
81//!         None => {
82//!             // Wait for the other thread to do the job
83//!             let (lock, cvar) = &*job.wait;
84//!             let mut done = lock.lock().unwrap();
85//!             // As long as the value inside the `Mutex<bool>` is `false`, we wait
86//!             while !*done {
87//!                 done = cvar.wait(done).unwrap();
88//!             }
89//!         }
90//!     }
91//!
92//!     // Read the output
93//!     job.output.get().unwrap().clone()
94//! }
95//!
96//! impl Input {
97//!     fn process(&mut self) -> Output {
98//!         // ...
99//! #       Output
100//!     }
101//! }
102//! # struct Input; #[derive(Clone)] struct Output;
103//! ```
104#![no_std]
105use core::{
106    cell::UnsafeCell,
107    mem::ManuallyDrop,
108    sync::atomic::{AtomicBool, Ordering},
109};
110
111/// A cell type which value can be taken only once.
112///
113/// See [crate-level documentation](mod@self) for more.
114#[derive(Default)]
115pub struct TakeCell<T: ?Sized> {
116    taken: AtomicBool,
117    value: UnsafeCell<T>,
118}
119
120impl<T> TakeCell<T> {
121    /// Creates a new `TakeCell` containing the given value.
122    pub const fn new(v: T) -> Self {
123        Self {
124            taken: AtomicBool::new(false),
125            value: UnsafeCell::new(v),
126        }
127    }
128
129    /// Unwraps the underlying value.
130    pub fn into_inner(self) -> T {
131        // TODO: make `into_inner` `const` when `UnsafeCell::into_inner` as `const fn`
132        // will be stabilized.
133        self.value.into_inner()
134    }
135}
136
137impl<T: ?Sized> TakeCell<T> {
138    /// Returns a reference to the underlying value.
139    ///
140    /// After this function once returns `Some(_)` all consequtive calls before
141    /// [`heal`] will return `None` as the reference is already taken.
142    ///
143    /// [`heal`]: TakeCell::heal
144    ///
145    /// ## Examples
146    ///
147    /// ```
148    /// # use takecell::TakeCell;
149    /// let cell = TakeCell::new(0);
150    ///
151    /// let uref: &mut _ = cell.take().unwrap();
152    /// *uref = 17;
153    ///
154    /// // Already taken
155    /// assert!(cell.take().is_none());
156    ///
157    /// let value = cell.into_inner();
158    /// assert_eq!(value, 17);
159    /// ```
160    pub fn take(&self) -> Option<&mut T> {
161        // ## Safety
162        //
163        // Aside from `steal` (that is unsafe and it's caller must guarantee that there
164        // are no concurent calls to `steal`/`take`) this is the only place where we are
165        // changing the value of `self.taken`.
166        //
167        // This is also the only place (again, aside from `steal`) where we use/provide
168        // a reference to the underlying value.
169        //
170        // Since this `swap` only changes the value from `false` to `true`, it can only
171        // return `false` once. This guarantees that the returned reference is
172        // unique.
173        //
174        // Two threads can't both swap false->true, this is guaranteed by the
175        // specification:
176        // > All modifications to any particular atomic variable
177        // > occur in a total order that is specific to this one atomic variable.
178        // > <https://en.cppreference.com/w/cpp/atomic/memory_order>
179        //
180        // `Relaxed` ordering is ok to use here, because when `TakeCell` is shared we
181        // only allow one (1) thread to access the protected memory, so there is no need
182        // to synchronize the memory between threads. When `TakeCell` is not shared and
183        // can be accessed with `get`, the thread that is holding `&mut TakeCell<_>`
184        // must have already synchronized itself with other threads so, again, there is
185        // no need for additional synchronization here. See also:
186        // <https://discord.com/channels/500028886025895936/628283088555737089/929435782370955344>.
187        match self.taken.swap(true, Ordering::Relaxed) {
188            // The cell was previously taken
189            true => None,
190            // The cell wasn't takes before, so we can take it
191            false => Some(unsafe { &mut *self.value.get() }),
192        }
193    }
194
195    /// Returns `true` if a reference to the underlying value has been already
196    /// [`take`]n.
197    ///
198    /// ie if this function returns `true`, then [`take`] will return `None`.
199    /// Note however that the oposite is not true: if this function returned
200    /// `false` it doesn't guarantee that [`take`] will return `Some(_)` since
201    /// there may have been concurent calls to [`take`].
202    ///
203    /// [`take`]: TakeCell::take
204    pub fn is_taken(&self) -> bool {
205        self.taken.load(Ordering::Relaxed)
206    }
207
208    /// Returns a unique reference to the underlying data.
209    ///
210    /// This call borrows `TakeCell` uniquely (at compile-time) which guarantees
211    /// that we possess the only reference.
212    ///
213    /// Note that this function is not affected nor affects the [`take`]. ie
214    /// this function will return a reference even if [`take`] was already
215    /// called
216    ///
217    /// [`take`]: TakeCell::take
218    pub fn get(&mut self) -> &mut T {
219        // TODO: make `get` `const` when `UnsafeCell::get_mut` as `const fn`
220        // will be stabilized.
221        self.value.get_mut()
222    }
223
224    /// Heal this cell. After a call to this function next call to [`take`] will
225    /// succeed again, even if [`take`] was called before.
226    ///
227    /// ## Examples
228    ///
229    /// ```
230    /// # use takecell::TakeCell;
231    /// let mut cell = TakeCell::new(0);
232    ///
233    /// assert!(cell.take().is_some());
234    /// assert!(cell.is_taken());
235    ///
236    /// cell.heal();
237    ///
238    /// assert!(!cell.is_taken());
239    /// assert!(cell.take().is_some());
240    /// ```
241    ///
242    /// [`take`]: TakeCell::take
243    pub fn heal(&mut self) {
244        // Unique reference to self guarantees that the reference retuened from
245        // `take`/`steal` (if these function were even called) is dead, thus it's okay
246        // to allow a new unique reference to the underlying value to be created.
247        self.taken = AtomicBool::new(false);
248    }
249
250    /// Similar to [`is_taken`], but uses unique reference instead of runtime
251    /// synchronization.
252    ///
253    /// [`is_taken`]: TakeCell::is_taken
254    pub fn is_taken_unsync(&mut self) -> bool {
255        *self.taken.get_mut()
256    }
257
258    /// Similar to [`take`], but uses unique reference instead of runtime
259    /// synchronization.
260    ///
261    /// [`take`]: TakeCell::take
262    pub fn take_unsync(&mut self) -> Option<&mut T> {
263        match self.is_taken_unsync() {
264            false => {
265                *self.taken.get_mut() = true;
266                Some(self.get())
267            }
268            true => None,
269        }
270    }
271
272    /// Unchecked version of [`take`].
273    ///
274    /// ## Safety
275    ///
276    /// Call to this function must be the first call to [`steal`] or [`take`]
277    /// after cell creation or [`heal`].
278    ///
279    /// [`take`]: TakeCell::take
280    /// [`steal`]: TakeCell::steal
281    /// [`heal`]: TakeCell::heal
282    #[allow(clippy::mut_from_ref)]
283    pub unsafe fn steal(&self) -> &mut T {
284        self.taken.store(true, Ordering::Relaxed);
285
286        // ## Safety
287        //
288        // Guaranteed by the caller
289        &mut *self.value.get()
290    }
291}
292
293impl<T> From<T> for TakeCell<T> {
294    fn from(v: T) -> Self {
295        Self::new(v)
296    }
297}
298
299/// ## Safety
300///
301/// It is possible to pass ownership via `&TakeCell`. As such, `TakeCell<T>` may
302/// be `Sync` (`TakeCell<T>: Send`) if and only if `T` is `Send`. Otherwise
303/// there may be UB, see [this example], adopted from sslab-gatech rust group.
304///
305/// [this example]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c5add45a552290fc206fe2e9c768e03f
306///
307/// `Sync` on the other hand is not required because `TakeCell`'s value is only
308/// accesible from one thread at a time.
309///
310/// This is again similar to a `Mutex`.
311unsafe impl<T: ?Sized + Send> Sync for TakeCell<T> {}
312
313/// A cell type which value can be taken only once.
314///
315/// In difference with [`TakeCell`](crate::TakeCell), this type provides
316/// ownership, and not a reference to the inner value. Because of this it can't
317/// contain unsized values.
318///
319/// See [crate-level documentation](mod@self) for more.
320#[derive(Default)]
321pub struct TakeOwnCell<T>(
322    // Invariant: `TakeCell::taken` is true <=> `ManuallyDrop`'s value was taken
323    TakeCell<ManuallyDrop<T>>,
324);
325
326impl<T> TakeOwnCell<T> {
327    /// Creates a new `TakeOwnCell` containing the given value.
328    pub const fn new(v: T) -> Self {
329        Self(TakeCell::new(ManuallyDrop::new(v)))
330    }
331
332    /// Returns the underlying value.
333    ///
334    /// After this function once returns `Some(_)` all consequtive calls before
335    /// [`heal`] will return `None` as the value is already taken.
336    ///
337    /// [`heal`]: TakeOwnCell::heal
338    ///
339    /// ## Examples
340    ///
341    /// ```
342    /// # use takecell::TakeOwnCell;
343    /// let cell = TakeOwnCell::new(17);
344    ///
345    /// let value: i32 = cell.take().unwrap();
346    /// assert_eq!(value, 17);
347    ///
348    /// // Already taken
349    /// assert!(cell.take().is_none());
350    /// assert!(cell.into_inner().is_none());
351    /// ```
352    pub fn take(&self) -> Option<T> {
353        self.0
354            .take()
355            // ## Safety
356            //
357            // `TakeCell` guatantees that unique reference to the underlying value is returned only
358            // once before `TakeCell::heal`. We ensure a new value is emplaced if it was taken
359            // before calling `TakeCell::heal`.
360            //
361            // In all other places (like `drop` and `get`) we check if the value was taken.
362            //
363            // This guarantees that the value is not duplicated.
364            .map(|value| unsafe { ManuallyDrop::take(value) })
365    }
366
367    /// Returns `true` if the underlying value has been already [`take`]n.
368    ///
369    /// ie if this function returns `true`, then [`take`] will return `None`.
370    /// Note however that the oposite is not true: if this function returned
371    /// `false` it doesn't guarantee that [`take`] will return `Some(_)` since
372    /// there may have been concurent calls to [`take`].
373    ///
374    /// [`take`]: TakeOwnCell::take
375    pub fn is_taken(&self) -> bool {
376        self.0.is_taken()
377    }
378
379    /// Returns a unique reference to the underlying data.
380    ///
381    /// This call borrows `TakeOwnCell` uniquely (at compile-time) which
382    /// guarantees that we possess the only reference.
383    ///
384    /// Note that this function does not affect the [`take`]. ie [`take`] may
385    /// still return `Some(_)` after a call to this function. The oposite is not
386    /// true, after the value is [`take`]n this function returns `None`.
387    ///
388    /// [`take`]: TakeOwnCell::take
389    pub fn get(&mut self) -> Option<&mut T> {
390        match self.is_taken() {
391            false => {
392                // ## Safety
393                //
394                // While this code doesn't use `unsafe{}` it can be affected by other unsafe
395                // blocks (see: `take`).
396                //
397                // The value may only be accessed if it was not taken before.
398                Some(&mut *self.0.get())
399            }
400            true => None,
401        }
402    }
403
404    /// Unwraps the underlying value.
405    pub fn into_inner(mut self) -> Option<T> {
406        self.take_unsync()
407    }
408
409    /// Heal this cell. After a call to this function next call to [`take`] will
410    /// succeed again, even if [`take`] was called before.
411    ///
412    /// Returns a reference to the underlying value and `Err(v)` if this cell
413    /// was not taken before the call to this function.
414    ///
415    /// ## Examples
416    ///
417    /// ```
418    /// # use takecell::TakeOwnCell;
419    /// let mut cell = TakeOwnCell::new(17);
420    ///
421    /// let (uref, res) = cell.heal(12);
422    /// assert_eq!(res, Err(12));
423    /// assert_eq!(*uref, 17);
424    /// *uref = 0xAA;
425    ///
426    /// assert_eq!(cell.take(), Some(0xAA));
427    ///
428    /// let (uref, res) = cell.heal(12);
429    /// assert!(res.is_ok());
430    /// assert_eq!(*uref, 12);
431    /// *uref = 0xBB;
432    ///
433    /// assert_eq!(cell.into_inner(), Some(0xBB));
434    /// ```
435    ///
436    /// [`take`]: TakeCell::take
437    pub fn heal(&mut self, v: T) -> (&mut T, Result<(), T>) {
438        // ## Safety
439        //
440        // While this code doesn't use `unsafe{}` it can be affected by other unsafe
441        // blocks (see: `take`).
442        //
443        // The value must be emplaced if it was previously taken, before healing the
444        // underlying cell.
445
446        let res = match self.0.is_taken() {
447            true => {
448                *self.0.get() = ManuallyDrop::new(v);
449                Ok(())
450            }
451            false => Err(v),
452        };
453
454        self.0.heal();
455
456        let uref = &mut *self.0.get();
457        (uref, res)
458    }
459
460    /// Similar to [`is_taken`], but uses unique reference instead of runtime
461    /// synchronization.
462    ///
463    /// [`is_taken`]: TakeOwnCell::is_taken
464    pub fn is_taken_unsync(&mut self) -> bool {
465        self.0.is_taken_unsync()
466    }
467
468    /// Similar to [`take`], but uses unique reference instead of runtime
469    /// synchronization.
470    ///
471    /// [`take`]: TakeOwnCell::take
472    pub fn take_unsync(&mut self) -> Option<T> {
473        self.0
474            .take_unsync()
475            // ## Safety
476            //
477            // `TakeCell` guatantees that unique reference to the underlying value is returned only
478            // once before `TakeCell::heal`. We ensure a new value is emplaced if it was taken
479            // before calling `TakeCell::heal`.
480            //
481            // In all other places (like `drop` and `get`) we check if the value was taken.
482            //
483            // This guarantees that the value is not duplicated.
484            .map(|value| unsafe { ManuallyDrop::take(value) })
485    }
486
487    /// Unchecked version of [`take`].
488    ///
489    /// ## Safety
490    ///
491    /// Call to this function must be the first call to [`steal`] or [`take`]
492    /// after cell creation or [`heal`].
493    ///
494    /// [`take`]: TakeOwnCell::take
495    /// [`steal`]: TakeOwnCell::steal
496    /// [`heal`]: TakeOwnCell::heal
497    pub unsafe fn steal(&self) -> T {
498        // ## Safety
499        //
500        // Guaranteed by the caller
501        ManuallyDrop::take(self.0.steal())
502    }
503}
504
505impl<T> From<T> for TakeOwnCell<T> {
506    fn from(v: T) -> Self {
507        Self::new(v)
508    }
509}
510
511/// ## Safety
512///
513/// It is possible to pass ownership via `&TakeOwnCell`. As such,
514/// `TakeOwnCell<T>` may be `Sync` (`TakeOwnCell<T>: Send`) if and only if `T`
515/// is `Send`. Otherwise there may be UB, see [this example], adopted from
516/// sslab-gatech rust group.
517///
518/// [this example]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c5add45a552290fc206fe2e9c768e03f
519///
520/// `Sync` on the other hand is not required because `TakeOwnCell`'s value is
521/// only accesible from one thread at a time.
522///
523/// This is again similar to a `Mutex`.
524unsafe impl<T: Send> Sync for TakeOwnCell<T> {}
525
526impl<T> Drop for TakeOwnCell<T> {
527    fn drop(&mut self) {
528        // Drop the underlying value, if the cell still holds it
529        let _ = self.take_unsync();
530    }
531}
532
533#[cfg(test)]
534mod tests {
535    use crate::TakeCell;
536
537    #[test]
538    fn it_works() {
539        let cell = TakeCell::new(0);
540
541        {
542            let uref = cell.take().unwrap();
543            *uref += 1;
544            assert_eq!(*uref, 1);
545
546            assert!(cell.take().is_none());
547
548            *uref += 1;
549            assert_eq!(*uref, 2);
550        }
551
552        assert!(cell.take().is_none());
553        assert_eq!(cell.into_inner(), 2);
554    }
555
556    #[test]
557    fn unsize() {
558        let cell: TakeCell<[i32; 10]> = TakeCell::new([0; 10]);
559
560        let _: &TakeCell<[i32]> = &cell;
561        let _: &TakeCell<dyn Send> = &cell;
562    }
563
564    #[test]
565    fn r#static() {
566        static CELL: TakeCell<i32> = TakeCell::new(0);
567
568        {
569            let uref: &'static mut i32 = CELL.take().unwrap();
570            *uref += 1;
571            assert_eq!(*uref, 1);
572
573            assert!(CELL.take().is_none());
574
575            *uref += 1;
576            assert_eq!(*uref, 2);
577        }
578
579        assert!(CELL.take().is_none());
580    }
581
582    #[test]
583    fn steal_takes() {
584        let cell = TakeCell::new(0);
585
586        // ## Safety
587        //
588        // There was no calls to take or steal before
589        let uref = unsafe { cell.steal() };
590        *uref += 1;
591        assert_eq!(*uref, 1);
592
593        assert!(cell.is_taken());
594        assert!(cell.take().is_none());
595
596        *uref += 1;
597        assert_eq!(*uref, 2);
598        assert_eq!(cell.into_inner(), 2);
599    }
600}
601
602#[cfg(test)]
603mod own_tests {
604    use crate::TakeOwnCell;
605
606    #[test]
607    fn it_works() {
608        let cell = TakeOwnCell::new(17);
609
610        assert_eq!(cell.take(), Some(17));
611
612        assert!(cell.take().is_none());
613        assert!(cell.into_inner().is_none());
614    }
615
616    #[test]
617    fn heal() {
618        let mut cell = TakeOwnCell::new(17);
619
620        let (uref, res) = cell.heal(12);
621        assert_eq!(res, Err(12));
622        assert_eq!(*uref, 17);
623        *uref = 0xAA;
624
625        assert_eq!(cell.take(), Some(0xAA));
626
627        let (uref, res) = cell.heal(12);
628        assert!(res.is_ok());
629        assert_eq!(*uref, 12);
630        *uref = 0xBB;
631
632        assert_eq!(cell.into_inner(), Some(0xBB));
633    }
634
635    #[test]
636    fn r#static() {
637        static CELL: TakeOwnCell<i32> = TakeOwnCell::new(42);
638
639        assert!(!CELL.is_taken());
640
641        assert_eq!(CELL.take(), Some(42));
642
643        assert!(CELL.is_taken());
644        assert!(CELL.take().is_none());
645    }
646
647    #[test]
648    fn steal_takes() {
649        let cell = TakeOwnCell::new(1);
650
651        assert!(!cell.is_taken());
652
653        // ## Safety
654        //
655        // There was no calls to take or steal before
656        assert_eq!(unsafe { cell.steal() }, 1);
657
658        assert!(cell.is_taken());
659        assert!(cell.take().is_none());
660        assert!(cell.into_inner().is_none());
661    }
662}