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(order: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: &T| 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}
681