lazycell/
lib.rs

1// Original work Copyright (c) 2014 The Rust Project Developers
2// Modified work Copyright (c) 2016-2020 Nikita Pekin and the lazycell contributors
3// See the README.md file at the top-level directory of this distribution.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11#![cfg_attr(not(test), no_std)]
12
13#![deny(missing_docs)]
14#![cfg_attr(feature = "nightly", feature(plugin))]
15#![cfg_attr(feature = "clippy", plugin(clippy))]
16
17//! This crate provides a `LazyCell` struct which acts as a lazily filled
18//! `Cell`.
19//!
20//! With a `RefCell`, the inner contents cannot be borrowed for the lifetime of
21//! the entire object, but only of the borrows returned. A `LazyCell` is a
22//! variation on `RefCell` which allows borrows to be tied to the lifetime of
23//! the outer object.
24//!
25//! # Example
26//!
27//! The following example shows a quick example of the basic functionality of
28//! `LazyCell`.
29//!
30//! ```
31//! use lazycell::LazyCell;
32//!
33//! let lazycell = LazyCell::new();
34//!
35//! assert_eq!(lazycell.borrow(), None);
36//! assert!(!lazycell.filled());
37//! lazycell.fill(1).ok();
38//! assert!(lazycell.filled());
39//! assert_eq!(lazycell.borrow(), Some(&1));
40//! assert_eq!(lazycell.into_inner(), Some(1));
41//! ```
42//!
43//! `AtomicLazyCell` is a variant that uses an atomic variable to manage
44//! coordination in a thread-safe fashion. The limitation of an `AtomicLazyCell`
45//! is that after it is initialized, it can't be modified.
46
47
48#[cfg(not(test))]
49#[macro_use]
50extern crate core as std;
51#[cfg(feature = "serde")]
52extern crate serde;
53
54#[cfg(feature = "serde")]
55mod serde_impl;
56
57use std::cell::UnsafeCell;
58use std::mem;
59use std::sync::atomic::{AtomicUsize, Ordering};
60
61/// A lazily filled `Cell`, with mutable contents.
62///
63/// A `LazyCell` is completely frozen once filled, **unless** you have `&mut`
64/// access to it, in which case `LazyCell::borrow_mut` may be used to mutate the
65/// contents.
66#[derive(Debug)]
67pub struct LazyCell<T> {
68    inner: UnsafeCell<Option<T>>,
69}
70
71impl<T> LazyCell<T> {
72    /// Creates a new, empty, `LazyCell`.
73    pub fn new() -> LazyCell<T> {
74        LazyCell { inner: UnsafeCell::new(None) }
75    }
76
77    /// Put a value into this cell.
78    ///
79    /// This function will return `Err(value)` if the cell is already full.
80    pub fn fill(&self, value: T) -> Result<(), T> {
81        let slot = unsafe { &*self.inner.get() };
82        if slot.is_some() {
83            return Err(value);
84        }
85        let slot = unsafe { &mut *self.inner.get() };
86        *slot = Some(value);
87
88        Ok(())
89    }
90
91    /// Put a value into this cell.
92    ///
93    /// Note that this function is infallible but requires `&mut self`. By
94    /// requiring `&mut self` we're guaranteed that no active borrows to this
95    /// cell can exist so we can always fill in the value. This may not always
96    /// be usable, however, as `&mut self` may not be possible to borrow.
97    ///
98    /// # Return value
99    ///
100    /// This function returns the previous value, if any.
101    pub fn replace(&mut self, value: T) -> Option<T> {
102        mem::replace(unsafe { &mut *self.inner.get() }, Some(value))
103    }
104
105    /// Test whether this cell has been previously filled.
106    pub fn filled(&self) -> bool {
107        self.borrow().is_some()
108    }
109
110    /// Borrows the contents of this lazy cell for the duration of the cell
111    /// itself.
112    ///
113    /// This function will return `Some` if the cell has been previously
114    /// initialized, and `None` if it has not yet been initialized.
115    pub fn borrow(&self) -> Option<&T> {
116        unsafe { &*self.inner.get() }.as_ref()
117    }
118
119    /// Borrows the contents of this lazy cell mutably for the duration of the cell
120    /// itself.
121    ///
122    /// This function will return `Some` if the cell has been previously
123    /// initialized, and `None` if it has not yet been initialized.
124    pub fn borrow_mut(&mut self) -> Option<&mut T> {
125        unsafe { &mut *self.inner.get() }.as_mut()
126    }
127
128    /// Borrows the contents of this lazy cell for the duration of the cell
129    /// itself.
130    ///
131    /// If the cell has not yet been filled, the cell is first filled using the
132    /// function provided.
133    ///
134    /// # Panics
135    ///
136    /// Panics if the cell becomes filled as a side effect of `f`.
137    pub fn borrow_with<F: FnOnce() -> T>(&self, f: F) -> &T {
138        if let Some(value) = self.borrow() {
139            return value;
140        }
141        let value = f();
142        if self.fill(value).is_err() {
143            panic!("borrow_with: cell was filled by closure")
144        }
145        self.borrow().unwrap()
146    }
147
148    /// Borrows the contents of this `LazyCell` mutably for the duration of the
149    /// cell itself.
150    ///
151    /// If the cell has not yet been filled, the cell is first filled using the
152    /// function provided.
153    ///
154    /// # Panics
155    ///
156    /// Panics if the cell becomes filled as a side effect of `f`.
157    pub fn borrow_mut_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
158        if !self.filled() {
159            let value = f();
160            if self.fill(value).is_err() {
161                panic!("borrow_mut_with: cell was filled by closure")
162            }
163        }
164
165        self.borrow_mut().unwrap()
166    }
167
168    /// Same as `borrow_with`, but allows the initializing function to fail.
169    ///
170    /// # Panics
171    ///
172    /// Panics if the cell becomes filled as a side effect of `f`.
173    pub fn try_borrow_with<E, F>(&self, f: F) -> Result<&T, E>
174        where F: FnOnce() -> Result<T, E>
175    {
176        if let Some(value) = self.borrow() {
177            return Ok(value);
178        }
179        let value = f()?;
180        if self.fill(value).is_err() {
181            panic!("try_borrow_with: cell was filled by closure")
182        }
183        Ok(self.borrow().unwrap())
184    }
185
186    /// Same as `borrow_mut_with`, but allows the initializing function to fail.
187    ///
188    /// # Panics
189    ///
190    /// Panics if the cell becomes filled as a side effect of `f`.
191    pub fn try_borrow_mut_with<E, F>(&mut self, f: F) -> Result<&mut T, E>
192        where F: FnOnce() -> Result<T, E>
193    {
194        if self.filled() {
195            return Ok(self.borrow_mut().unwrap());
196        }
197        let value = f()?;
198        if self.fill(value).is_err() {
199            panic!("try_borrow_mut_with: cell was filled by closure")
200        }
201        Ok(self.borrow_mut().unwrap())
202    }
203
204    /// Consumes this `LazyCell`, returning the underlying value.
205    pub fn into_inner(self) -> Option<T> {
206        // Rust 1.25 changed UnsafeCell::into_inner() from unsafe to safe
207        // function. This unsafe can be removed when supporting Rust older than
208        // 1.25 is not needed.
209        #[allow(unused_unsafe)]
210        unsafe { self.inner.into_inner() }
211    }
212}
213
214impl<T: Copy> LazyCell<T> {
215    /// Returns a copy of the contents of the lazy cell.
216    ///
217    /// This function will return `Some` if the cell has been previously initialized,
218    /// and `None` if it has not yet been initialized.
219    pub fn get(&self) -> Option<T> {
220        unsafe { *self.inner.get() }
221    }
222}
223
224impl<T> Default for LazyCell<T> {
225    fn default() -> Self {
226        Self::new()
227    }
228}
229
230impl <T: Clone> Clone for LazyCell<T> {
231    /// Create a clone of this `LazyCell`
232    ///
233    /// If self has not been initialized, returns an uninitialized `LazyCell`
234    /// otherwise returns a `LazyCell` already initialized with a clone of the
235    /// contents of self.
236    fn clone(&self) -> LazyCell<T> {
237        LazyCell { inner: UnsafeCell::new(self.borrow().map(Clone::clone) ) }
238    }
239}
240
241// Tracks the AtomicLazyCell inner state
242const NONE: usize = 0;
243const LOCK: usize = 1;
244const SOME: usize = 2;
245
246/// A lazily filled and thread-safe `Cell`, with frozen contents.
247#[derive(Debug)]
248pub struct AtomicLazyCell<T> {
249    inner: UnsafeCell<Option<T>>,
250    state: AtomicUsize,
251}
252
253impl<T> AtomicLazyCell<T> {
254    /// An empty `AtomicLazyCell`.
255    pub const NONE: Self = Self {
256        inner: UnsafeCell::new(None),
257        state: AtomicUsize::new(NONE),
258    };
259
260    /// Creates a new, empty, `AtomicLazyCell`.
261    pub fn new() -> AtomicLazyCell<T> {
262        Self::NONE
263    }
264
265    /// Put a value into this cell.
266    ///
267    /// This function will return `Err(value)` if the cell is already full.
268    pub fn fill(&self, t: T) -> Result<(), T> {
269        if NONE != self.state.compare_and_swap(NONE, LOCK, Ordering::Acquire) {
270            return Err(t);
271        }
272
273        unsafe { *self.inner.get() = Some(t) };
274
275        if LOCK != self.state.compare_and_swap(LOCK, SOME, Ordering::Release) {
276            panic!("unable to release lock");
277        }
278
279        Ok(())
280    }
281
282    /// Put a value into this cell.
283    ///
284    /// Note that this function is infallible but requires `&mut self`. By
285    /// requiring `&mut self` we're guaranteed that no active borrows to this
286    /// cell can exist so we can always fill in the value. This may not always
287    /// be usable, however, as `&mut self` may not be possible to borrow.
288    ///
289    /// # Return value
290    ///
291    /// This function returns the previous value, if any.
292    pub fn replace(&mut self, value: T) -> Option<T> {
293        match mem::replace(self.state.get_mut(), SOME) {
294            NONE | SOME => {}
295            _ => panic!("cell in inconsistent state"),
296        }
297        mem::replace(unsafe { &mut *self.inner.get() }, Some(value))
298    }
299
300    /// Test whether this cell has been previously filled.
301    pub fn filled(&self) -> bool {
302        self.state.load(Ordering::Acquire) == SOME
303    }
304
305    /// Borrows the contents of this lazy cell for the duration of the cell
306    /// itself.
307    ///
308    /// This function will return `Some` if the cell has been previously
309    /// initialized, and `None` if it has not yet been initialized.
310    pub fn borrow(&self) -> Option<&T> {
311        match self.state.load(Ordering::Acquire) {
312            SOME => unsafe { &*self.inner.get() }.as_ref(),
313            _ => None,
314        }
315    }
316
317    /// Consumes this `LazyCell`, returning the underlying value.
318    pub fn into_inner(self) -> Option<T> {
319        // Rust 1.25 changed UnsafeCell::into_inner() from unsafe to safe
320        // function. This unsafe can be removed when supporting Rust older than
321        // 1.25 is not needed.
322        #[allow(unused_unsafe)]
323        unsafe { self.inner.into_inner() }
324    }
325}
326
327impl<T: Copy> AtomicLazyCell<T> {
328    /// Returns a copy of the contents of the lazy cell.
329    ///
330    /// This function will return `Some` if the cell has been previously initialized,
331    /// and `None` if it has not yet been initialized.
332    pub fn get(&self) -> Option<T> {
333        match self.state.load(Ordering::Acquire) {
334            SOME => unsafe { *self.inner.get() },
335            _ => None,
336        }
337    }
338}
339
340impl<T> Default for AtomicLazyCell<T> {
341    fn default() -> Self {
342        Self::new()
343    }
344}
345
346impl<T: Clone> Clone for AtomicLazyCell<T> {
347    /// Create a clone of this `AtomicLazyCell`
348    ///
349    /// If self has not been initialized, returns an uninitialized `AtomicLazyCell`
350    /// otherwise returns an `AtomicLazyCell` already initialized with a clone of the
351    /// contents of self.
352    fn clone(&self) -> AtomicLazyCell<T> {
353        self.borrow().map_or(
354            Self::NONE,
355            |v| AtomicLazyCell {
356                inner: UnsafeCell::new(Some(v.clone())),
357                state: AtomicUsize::new(SOME),
358            }
359        )
360    }
361}
362
363unsafe impl<T: Sync + Send> Sync for AtomicLazyCell<T> {}
364
365unsafe impl<T: Send> Send for AtomicLazyCell<T> {}
366
367#[cfg(test)]
368mod tests {
369    use super::{AtomicLazyCell, LazyCell};
370
371    #[test]
372    fn test_borrow_from_empty() {
373        let lazycell: LazyCell<usize> = LazyCell::new();
374
375        let value = lazycell.borrow();
376        assert_eq!(value, None);
377
378        let value = lazycell.get();
379        assert_eq!(value, None);
380    }
381
382    #[test]
383    fn test_fill_and_borrow() {
384        let lazycell = LazyCell::new();
385
386        assert!(!lazycell.filled());
387        lazycell.fill(1).unwrap();
388        assert!(lazycell.filled());
389
390        let value = lazycell.borrow();
391        assert_eq!(value, Some(&1));
392
393        let value = lazycell.get();
394        assert_eq!(value, Some(1));
395    }
396
397    #[test]
398    fn test_borrow_mut() {
399        let mut lazycell = LazyCell::new();
400        assert!(lazycell.borrow_mut().is_none());
401
402        lazycell.fill(1).unwrap();
403        assert_eq!(lazycell.borrow_mut(), Some(&mut 1));
404
405        *lazycell.borrow_mut().unwrap() = 2;
406        assert_eq!(lazycell.borrow_mut(), Some(&mut 2));
407
408        // official way to reset the cell
409        lazycell = LazyCell::new();
410        assert!(lazycell.borrow_mut().is_none());
411    }
412
413    #[test]
414    fn test_already_filled_error() {
415        let lazycell = LazyCell::new();
416
417        lazycell.fill(1).unwrap();
418        assert_eq!(lazycell.fill(1), Err(1));
419    }
420
421    #[test]
422    fn test_borrow_with() {
423        let lazycell = LazyCell::new();
424
425        let value = lazycell.borrow_with(|| 1);
426        assert_eq!(&1, value);
427    }
428
429    #[test]
430    fn test_borrow_with_already_filled() {
431        let lazycell = LazyCell::new();
432        lazycell.fill(1).unwrap();
433
434        let value = lazycell.borrow_with(|| 1);
435        assert_eq!(&1, value);
436    }
437
438    #[test]
439    fn test_borrow_with_not_called_when_filled() {
440        let lazycell = LazyCell::new();
441
442        lazycell.fill(1).unwrap();
443
444        let value = lazycell.borrow_with(|| 2);
445        assert_eq!(&1, value);
446    }
447
448    #[test]
449    #[should_panic]
450    fn test_borrow_with_sound_with_reentrancy() {
451        // Kudos to dbaupp for discovering this issue
452        // https://www.reddit.com/r/rust/comments/5vs9rt/lazycell_a_rust_library_providing_a_lazilyfilled/de527xm/
453        let lazycell: LazyCell<Box<i32>> = LazyCell::new();
454
455        let mut reference: Option<&i32> = None;
456
457        lazycell.borrow_with(|| {
458            let _ = lazycell.fill(Box::new(1));
459            reference = lazycell.borrow().map(|r| &**r);
460            Box::new(2)
461        });
462    }
463
464    #[test]
465    fn test_borrow_mut_with() {
466        let mut lazycell = LazyCell::new();
467
468        {
469            let value = lazycell.borrow_mut_with(|| 1);
470            assert_eq!(&mut 1, value);
471            *value = 2;
472        }
473        assert_eq!(&2, lazycell.borrow().unwrap());
474    }
475
476    #[test]
477    fn test_borrow_mut_with_already_filled() {
478        let mut lazycell = LazyCell::new();
479        lazycell.fill(1).unwrap();
480
481        let value = lazycell.borrow_mut_with(|| 1);
482        assert_eq!(&1, value);
483    }
484
485    #[test]
486    fn test_borrow_mut_with_not_called_when_filled() {
487        let mut lazycell = LazyCell::new();
488
489        lazycell.fill(1).unwrap();
490
491        let value = lazycell.borrow_mut_with(|| 2);
492        assert_eq!(&1, value);
493    }
494
495    #[test]
496    fn test_try_borrow_with_ok() {
497        let lazycell = LazyCell::new();
498        let result = lazycell.try_borrow_with::<(), _>(|| Ok(1));
499        assert_eq!(result, Ok(&1));
500    }
501
502    #[test]
503    fn test_try_borrow_with_err() {
504        let lazycell = LazyCell::<()>::new();
505        let result = lazycell.try_borrow_with(|| Err(1));
506        assert_eq!(result, Err(1));
507    }
508
509    #[test]
510    fn test_try_borrow_with_already_filled() {
511        let lazycell = LazyCell::new();
512        lazycell.fill(1).unwrap();
513        let result = lazycell.try_borrow_with::<(), _>(|| unreachable!());
514        assert_eq!(result, Ok(&1));
515    }
516
517    #[test]
518    #[should_panic]
519    fn test_try_borrow_with_sound_with_reentrancy() {
520        let lazycell: LazyCell<Box<i32>> = LazyCell::new();
521
522        let mut reference: Option<&i32> = None;
523
524        let _ = lazycell.try_borrow_with::<(), _>(|| {
525            let _ = lazycell.fill(Box::new(1));
526            reference = lazycell.borrow().map(|r| &**r);
527            Ok(Box::new(2))
528        });
529    }
530
531    #[test]
532    fn test_try_borrow_mut_with_ok() {
533        let mut lazycell = LazyCell::new();
534        {
535            let result = lazycell.try_borrow_mut_with::<(), _>(|| Ok(1));
536            assert_eq!(result, Ok(&mut 1));
537            *result.unwrap() = 2;
538        }
539        assert_eq!(&mut 2, lazycell.borrow().unwrap());
540    }
541
542    #[test]
543    fn test_try_borrow_mut_with_err() {
544        let mut lazycell = LazyCell::<()>::new();
545        let result = lazycell.try_borrow_mut_with(|| Err(1));
546        assert_eq!(result, Err(1));
547    }
548
549    #[test]
550    fn test_try_borrow_mut_with_already_filled() {
551        let mut lazycell = LazyCell::new();
552        lazycell.fill(1).unwrap();
553        let result = lazycell.try_borrow_mut_with::<(), _>(|| unreachable!());
554        assert_eq!(result, Ok(&mut 1));
555    }
556
557    #[test]
558    fn test_into_inner() {
559        let lazycell = LazyCell::new();
560
561        lazycell.fill(1).unwrap();
562        let value = lazycell.into_inner();
563        assert_eq!(value, Some(1));
564    }
565
566    #[test]
567    fn test_atomic_borrow_from_empty() {
568        let lazycell: AtomicLazyCell<usize> = AtomicLazyCell::new();
569
570        let value = lazycell.borrow();
571        assert_eq!(value, None);
572
573        let value = lazycell.get();
574        assert_eq!(value, None);
575    }
576
577    #[test]
578    fn test_atomic_fill_and_borrow() {
579        let lazycell = AtomicLazyCell::new();
580
581        assert!(!lazycell.filled());
582        lazycell.fill(1).unwrap();
583        assert!(lazycell.filled());
584
585        let value = lazycell.borrow();
586        assert_eq!(value, Some(&1));
587
588        let value = lazycell.get();
589        assert_eq!(value, Some(1));
590    }
591
592    #[test]
593    fn test_atomic_already_filled_panic() {
594        let lazycell = AtomicLazyCell::new();
595
596        lazycell.fill(1).unwrap();
597        assert_eq!(1, lazycell.fill(1).unwrap_err());
598    }
599
600    #[test]
601    fn test_atomic_into_inner() {
602        let lazycell = AtomicLazyCell::new();
603
604        lazycell.fill(1).unwrap();
605        let value = lazycell.into_inner();
606        assert_eq!(value, Some(1));
607    }
608
609    #[test]
610    fn normal_replace() {
611        let mut cell = LazyCell::new();
612        assert_eq!(cell.fill(1), Ok(()));
613        assert_eq!(cell.replace(2), Some(1));
614        assert_eq!(cell.replace(3), Some(2));
615        assert_eq!(cell.borrow(), Some(&3));
616
617        let mut cell = LazyCell::new();
618        assert_eq!(cell.replace(2), None);
619    }
620
621    #[test]
622    fn atomic_replace() {
623        let mut cell = AtomicLazyCell::new();
624        assert_eq!(cell.fill(1), Ok(()));
625        assert_eq!(cell.replace(2), Some(1));
626        assert_eq!(cell.replace(3), Some(2));
627        assert_eq!(cell.borrow(), Some(&3));
628    }
629
630    #[test]
631    fn clone() {
632        let mut cell = LazyCell::new();
633        let clone1 = cell.clone();
634        assert_eq!(clone1.borrow(), None);
635        assert_eq!(cell.fill(1), Ok(()));
636        let mut clone2 = cell.clone();
637        assert_eq!(clone1.borrow(), None);
638        assert_eq!(clone2.borrow(), Some(&1));
639        assert_eq!(cell.replace(2), Some(1));
640        assert_eq!(clone1.borrow(), None);
641        assert_eq!(clone2.borrow(), Some(&1));
642        assert_eq!(clone1.fill(3), Ok(()));
643        assert_eq!(clone2.replace(4), Some(1));
644        assert_eq!(clone1.borrow(), Some(&3));
645        assert_eq!(clone2.borrow(), Some(&4));
646        assert_eq!(cell.borrow(), Some(&2));
647    }
648
649    #[test]
650    fn clone_atomic() {
651        let mut cell = AtomicLazyCell::new();
652        let clone1 = cell.clone();
653        assert_eq!(clone1.borrow(), None);
654        assert_eq!(cell.fill(1), Ok(()));
655        let mut clone2 = cell.clone();
656        assert_eq!(clone1.borrow(), None);
657        assert_eq!(clone2.borrow(), Some(&1));
658        assert_eq!(cell.replace(2), Some(1));
659        assert_eq!(clone1.borrow(), None);
660        assert_eq!(clone2.borrow(), Some(&1));
661        assert_eq!(clone1.fill(3), Ok(()));
662        assert_eq!(clone2.replace(4), Some(1));
663        assert_eq!(clone1.borrow(), Some(&3));
664        assert_eq!(clone2.borrow(), Some(&4));
665        assert_eq!(cell.borrow(), Some(&2));
666    }
667
668    #[test]
669    fn default() {
670        #[derive(Default)]
671        struct Defaultable;
672        struct NonDefaultable;
673
674        let _: LazyCell<Defaultable> = LazyCell::default();
675        let _: LazyCell<NonDefaultable> = LazyCell::default();
676
677        let _: AtomicLazyCell<Defaultable> = AtomicLazyCell::default();
678        let _: AtomicLazyCell<NonDefaultable> = AtomicLazyCell::default();
679    }
680}