1 // Original work Copyright (c) 2014 The Rust Project Developers
2 // Modified work Copyright (c) 2016-2018 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 #![deny(missing_docs)]
12 #![allow(unused)]
13 
14 //! This crate provides a `LazyCell` struct which acts as a lazily filled
15 //! `Cell`.
16 //!
17 //! With a `RefCell`, the inner contents cannot be borrowed for the lifetime of
18 //! the entire object, but only of the borrows returned. A `LazyCell` is a
19 //! variation on `RefCell` which allows borrows to be tied to the lifetime of
20 //! the outer object.
21 //!
22 //! `AtomicLazyCell` is a variant that uses an atomic variable to manage
23 //! coordination in a thread-safe fashion. The limitation of an `AtomicLazyCell`
24 //! is that after it is initialized, it can't be modified.
25 
26 use std::cell::UnsafeCell;
27 use std::mem;
28 use std::sync::atomic::{AtomicUsize, Ordering};
29 
30 /// A lazily filled `Cell`, with mutable contents.
31 ///
32 /// A `LazyCell` is completely frozen once filled, **unless** you have `&mut`
33 /// access to it, in which case `LazyCell::borrow_mut` may be used to mutate the
34 /// contents.
35 #[derive(Debug, Default)]
36 pub struct LazyCell<T> {
37     inner: UnsafeCell<Option<T>>,
38 }
39 
40 impl<T> LazyCell<T> {
41     /// Creates a new, empty, `LazyCell`.
42     pub fn new() -> LazyCell<T> {
43         LazyCell { inner: UnsafeCell::new(None) }
44     }
45 
46     /// Put a value into this cell.
47     ///
48     /// This function will return `Err(value)` is the cell is already full.
49     pub fn fill(&self, value: T) -> Result<(), T> {
50         let slot = unsafe { &mut *self.inner.get() };
51         if slot.is_some() {
52             return Err(value);
53         }
54         *slot = Some(value);
55 
56         Ok(())
57     }
58 
59     /// Put a value into this cell.
60     ///
61     /// Note that this function is infallible but requires `&mut self`. By
62     /// requiring `&mut self` we're guaranteed that no active borrows to this
63     /// cell can exist so we can always fill in the value. This may not always
64     /// be usable, however, as `&mut self` may not be possible to borrow.
65     ///
66     /// # Return value
67     ///
68     /// This function returns the previous value, if any.
69     pub fn replace(&mut self, value: T) -> Option<T> {
70         mem::replace(unsafe { &mut *self.inner.get() }, Some(value))
71     }
72 
73     /// Test whether this cell has been previously filled.
74     pub fn filled(&self) -> bool {
75         self.borrow().is_some()
76     }
77 
78     /// Borrows the contents of this lazy cell for the duration of the cell
79     /// itself.
80     ///
81     /// This function will return `Some` if the cell has been previously
82     /// initialized, and `None` if it has not yet been initialized.
find_minlength(const REAL_PCRE * re,const pcre_uchar * code,const pcre_uchar * startcode,int options,recurse_check * recurses,int * countptr)83     pub fn borrow(&self) -> Option<&T> {
84         unsafe { &*self.inner.get() }.as_ref()
85     }
86 
87     /// Borrows the contents of this lazy cell mutably for the duration of the cell
88     /// itself.
89     ///
90     /// This function will return `Some` if the cell has been previously
91     /// initialized, and `None` if it has not yet been initialized.
92     pub fn borrow_mut(&mut self) -> Option<&mut T> {
93         unsafe { &mut *self.inner.get() }.as_mut()
94     }
95 
96     /// Borrows the contents of this lazy cell for the duration of the cell
97     /// itself.
98     ///
99     /// If the cell has not yet been filled, the cell is first filled using the
100     /// function provided.
101     ///
102     /// # Panics
103     ///
104     /// Panics if the cell becomes filled as a side effect of `f`.
105     pub fn borrow_with<F: FnOnce() -> T>(&self, f: F) -> &T {
106         if let Some(value) = self.borrow() {
107             return value;
108         }
109         let value = f();
110         if self.fill(value).is_err() {
111             panic!("borrow_with: cell was filled by closure")
112         }
113         self.borrow().unwrap()
114     }
115 
116     /// Borrows the contents of this `LazyCell` mutably for the duration of the
117     /// cell itself.
118     ///
119     /// If the cell has not yet been filled, the cell is first filled using the
120     /// function provided.
121     ///
122     /// # Panics
123     ///
124     /// Panics if the cell becomes filled as a side effect of `f`.
125     pub fn borrow_mut_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
126         if !self.filled() {
127             let value = f();
128             if self.fill(value).is_err() {
129                 panic!("borrow_mut_with: cell was filled by closure")
130             }
131         }
132 
133         self.borrow_mut().unwrap()
134     }
135 
136     /// Same as `borrow_with`, but allows the initializing function to fail.
137     ///
138     /// # Panics
139     ///
140     /// Panics if the cell becomes filled as a side effect of `f`.
141     pub fn try_borrow_with<E, F>(&self, f: F) -> Result<&T, E>
142         where F: FnOnce() -> Result<T, E>
143     {
144         if let Some(value) = self.borrow() {
145             return Ok(value);
146         }
147         let value = f()?;
148         if self.fill(value).is_err() {
149             panic!("try_borrow_with: cell was filled by closure")
150         }
151         Ok(self.borrow().unwrap())
152     }
153 
154     /// Same as `borrow_mut_with`, but allows the initializing function to fail.
155     ///
156     /// # Panics
157     ///
158     /// Panics if the cell becomes filled as a side effect of `f`.
159     pub fn try_borrow_mut_with<E, F>(&mut self, f: F) -> Result<&mut T, E>
160         where F: FnOnce() -> Result<T, E>
161     {
162         if self.filled() {
163             return Ok(self.borrow_mut().unwrap());
164         }
165         let value = f()?;
166         if self.fill(value).is_err() {
167             panic!("try_borrow_mut_with: cell was filled by closure")
168         }
169         Ok(self.borrow_mut().unwrap())
170     }
171 
172     /// Consumes this `LazyCell`, returning the underlying value.
173     pub fn into_inner(self) -> Option<T> {
174         // Rust 1.25 changed UnsafeCell::into_inner() from unsafe to safe
175         // function. This unsafe can be removed when supporting Rust older than
176         // 1.25 is not needed.
177         #[allow(unused_unsafe)]
178         unsafe { self.inner.into_inner() }
179     }
180 }
181 
182 impl<T: Copy> LazyCell<T> {
183     /// Returns a copy of the contents of the lazy cell.
184     ///
185     /// This function will return `Some` if the cell has been previously initialized,
186     /// and `None` if it has not yet been initialized.
187     pub fn get(&self) -> Option<T> {
188         unsafe { *self.inner.get() }
189     }
190 }
191 
192 // Tracks the AtomicLazyCell inner state
193 const NONE: usize = 0;
194 const LOCK: usize = 1;
195 const SOME: usize = 2;
196 
197 /// A lazily filled and thread-safe `Cell`, with frozen contents.
198 #[derive(Debug, Default)]
199 pub struct AtomicLazyCell<T> {
200     inner: UnsafeCell<Option<T>>,
201     state: AtomicUsize,
202 }
203 
204 impl<T> AtomicLazyCell<T> {
205     /// Creates a new, empty, `AtomicLazyCell`.
206     pub fn new() -> AtomicLazyCell<T> {
207         Self {
208             inner: UnsafeCell::new(None),
209             state: AtomicUsize::new(NONE),
210         }
211     }
212 
213     /// Put a value into this cell.
214     ///
215     /// This function will return `Err(value)` is the cell is already full.
216     pub fn fill(&self, t: T) -> Result<(), T> {
217         if NONE != self.state.compare_and_swap(NONE, LOCK, Ordering::Acquire) {
218             return Err(t);
219         }
220 
221         unsafe { *self.inner.get() = Some(t) };
222 
223         if LOCK != self.state.compare_and_swap(LOCK, SOME, Ordering::Release) {
224             panic!("unable to release lock");
225         }
226 
227         Ok(())
228     }
229 
230     /// Put a value into this cell.
231     ///
232     /// Note that this function is infallible but requires `&mut self`. By
233     /// requiring `&mut self` we're guaranteed that no active borrows to this
234     /// cell can exist so we can always fill in the value. This may not always
235     /// be usable, however, as `&mut self` may not be possible to borrow.
236     ///
237     /// # Return value
238     ///
239     /// This function returns the previous value, if any.
240     pub fn replace(&mut self, value: T) -> Option<T> {
241         match mem::replace(self.state.get_mut(), SOME) {
242             NONE | SOME => {}
243             _ => panic!("cell in inconsistent state"),
244         }
245         mem::replace(unsafe { &mut *self.inner.get() }, Some(value))
246     }
247 
248     /// Test whether this cell has been previously filled.
249     pub fn filled(&self) -> bool {
250         self.state.load(Ordering::Acquire) == SOME
251     }
252 
253     /// Borrows the contents of this lazy cell for the duration of the cell
254     /// itself.
255     ///
256     /// This function will return `Some` if the cell has been previously
257     /// initialized, and `None` if it has not yet been initialized.
258     pub fn borrow(&self) -> Option<&T> {
259         match self.state.load(Ordering::Acquire) {
260             SOME => unsafe { &*self.inner.get() }.as_ref(),
261             _ => None,
262         }
263     }
264 
265     /// Consumes this `LazyCell`, returning the underlying value.
266     pub fn into_inner(self) -> Option<T> {
267         // Rust 1.25 changed UnsafeCell::into_inner() from unsafe to safe
268         // function. This unsafe can be removed when supporting Rust older than
269         // 1.25 is not needed.
270         #[allow(unused_unsafe)]
271         unsafe { self.inner.into_inner() }
272     }
273 }
274 
275 impl<T: Copy> AtomicLazyCell<T> {
276     /// Returns a copy of the contents of the lazy cell.
277     ///
278     /// This function will return `Some` if the cell has been previously initialized,
279     /// and `None` if it has not yet been initialized.
280     pub fn get(&self) -> Option<T> {
281         match self.state.load(Ordering::Acquire) {
282             SOME => unsafe { *self.inner.get() },
283             _ => None,
284         }
285     }
286 }
287 
288 unsafe impl<T: Sync + Send> Sync for AtomicLazyCell<T> {}
289 
290 unsafe impl<T: Send> Send for AtomicLazyCell<T> {}
291 
292 #[cfg(test)]
293 mod tests {
294     use super::{AtomicLazyCell, LazyCell};
295 
296     #[test]
297     fn test_borrow_from_empty() {
298         let lazycell: LazyCell<usize> = LazyCell::new();
299 
300         let value = lazycell.borrow();
301         assert_eq!(value, None);
302 
303         let value = lazycell.get();
304         assert_eq!(value, None);
305     }
306 
307     #[test]
308     fn test_fill_and_borrow() {
309         let lazycell = LazyCell::new();
310 
311         assert!(!lazycell.filled());
312         lazycell.fill(1).unwrap();
313         assert!(lazycell.filled());
314 
315         let value = lazycell.borrow();
316         assert_eq!(value, Some(&1));
317 
318         let value = lazycell.get();
319         assert_eq!(value, Some(1));
320     }
321 
322     #[test]
323     fn test_borrow_mut() {
324         let mut lazycell = LazyCell::new();
325         assert!(lazycell.borrow_mut().is_none());
326 
327         lazycell.fill(1).unwrap();
328         assert_eq!(lazycell.borrow_mut(), Some(&mut 1));
329 
330         *lazycell.borrow_mut().unwrap() = 2;
331         assert_eq!(lazycell.borrow_mut(), Some(&mut 2));
332 
333         // official way to reset the cell
334         lazycell = LazyCell::new();
335         assert!(lazycell.borrow_mut().is_none());
336     }
337 
338     #[test]
339     fn test_already_filled_error() {
340         let lazycell = LazyCell::new();
341 
342         lazycell.fill(1).unwrap();
343         assert_eq!(lazycell.fill(1), Err(1));
344     }
345 
346     #[test]
347     fn test_borrow_with() {
348         let lazycell = LazyCell::new();
349 
350         let value = lazycell.borrow_with(|| 1);
351         assert_eq!(&1, value);
352     }
353 
354     #[test]
355     fn test_borrow_with_already_filled() {
356         let lazycell = LazyCell::new();
357         lazycell.fill(1).unwrap();
358 
359         let value = lazycell.borrow_with(|| 1);
360         assert_eq!(&1, value);
361     }
362 
363     #[test]
364     fn test_borrow_with_not_called_when_filled() {
365         let lazycell = LazyCell::new();
366 
367         lazycell.fill(1).unwrap();
368 
369         let value = lazycell.borrow_with(|| 2);
370         assert_eq!(&1, value);
371     }
372 
373     #[test]
374     #[should_panic]
375     fn test_borrow_with_sound_with_reentrancy() {
376         // Kudos to dbaupp for discovering this issue
377         // https://www.reddit.com/r/rust/comments/5vs9rt/lazycell_a_rust_library_providing_a_lazilyfilled/de527xm/
378         let lazycell: LazyCell<Box<i32>> = LazyCell::new();
379 
380         let mut reference: Option<&i32> = None;
381 
382         lazycell.borrow_with(|| {
383             let _ = lazycell.fill(Box::new(1));
384             reference = lazycell.borrow().map(|r| &**r);
385             Box::new(2)
386         });
387     }
388 
389     #[test]
390     fn test_borrow_mut_with() {
391         let mut lazycell = LazyCell::new();
392 
393         {
394             let value = lazycell.borrow_mut_with(|| 1);
395             assert_eq!(&mut 1, value);
396             *value = 2;
397         }
398         assert_eq!(&2, lazycell.borrow().unwrap());
399     }
400 
401     #[test]
402     fn test_borrow_mut_with_already_filled() {
403         let mut lazycell = LazyCell::new();
404         lazycell.fill(1).unwrap();
405 
406         let value = lazycell.borrow_mut_with(|| 1);
407         assert_eq!(&1, value);
408     }
409 
410     #[test]
411     fn test_borrow_mut_with_not_called_when_filled() {
412         let mut lazycell = LazyCell::new();
413 
414         lazycell.fill(1).unwrap();
415 
416         let value = lazycell.borrow_mut_with(|| 2);
417         assert_eq!(&1, value);
418     }
419 
420     #[test]
421     fn test_try_borrow_with_ok() {
422         let lazycell = LazyCell::new();
423         let result = lazycell.try_borrow_with::<(), _>(|| Ok(1));
424         assert_eq!(result, Ok(&1));
425     }
426 
427     #[test]
428     fn test_try_borrow_with_err() {
429         let lazycell = LazyCell::<()>::new();
430         let result = lazycell.try_borrow_with(|| Err(1));
431         assert_eq!(result, Err(1));
432     }
433 
434     #[test]
435     fn test_try_borrow_with_already_filled() {
436         let lazycell = LazyCell::new();
437         lazycell.fill(1).unwrap();
438         let result = lazycell.try_borrow_with::<(), _>(|| unreachable!());
439         assert_eq!(result, Ok(&1));
440     }
441 
442     #[test]
443     #[should_panic]
444     fn test_try_borrow_with_sound_with_reentrancy() {
445         let lazycell: LazyCell<Box<i32>> = LazyCell::new();
446 
447         let mut reference: Option<&i32> = None;
448 
449         let _ = lazycell.try_borrow_with::<(), _>(|| {
450             let _ = lazycell.fill(Box::new(1));
451             reference = lazycell.borrow().map(|r| &**r);
452             Ok(Box::new(2))
453         });
454     }
455 
456     #[test]
457     fn test_try_borrow_mut_with_ok() {
458         let mut lazycell = LazyCell::new();
459         {
460             let result = lazycell.try_borrow_mut_with::<(), _>(|| Ok(1));
461             assert_eq!(result, Ok(&mut 1));
462             *result.unwrap() = 2;
463         }
464         assert_eq!(&mut 2, lazycell.borrow().unwrap());
465     }
466 
467     #[test]
468     fn test_try_borrow_mut_with_err() {
469         let mut lazycell = LazyCell::<()>::new();
470         let result = lazycell.try_borrow_mut_with(|| Err(1));
471         assert_eq!(result, Err(1));
472     }
473 
474     #[test]
475     fn test_try_borrow_mut_with_already_filled() {
476         let mut lazycell = LazyCell::new();
477         lazycell.fill(1).unwrap();
478         let result = lazycell.try_borrow_mut_with::<(), _>(|| unreachable!());
479         assert_eq!(result, Ok(&mut 1));
480     }
481 
482     #[test]
483     fn test_into_inner() {
484         let lazycell = LazyCell::new();
485 
486         lazycell.fill(1).unwrap();
487         let value = lazycell.into_inner();
488         assert_eq!(value, Some(1));
489     }
490 
491     #[test]
492     fn test_atomic_borrow_from_empty() {
493         let lazycell: AtomicLazyCell<usize> = AtomicLazyCell::new();
494 
495         let value = lazycell.borrow();
496         assert_eq!(value, None);
497 
498         let value = lazycell.get();
499         assert_eq!(value, None);
500     }
501 
502     #[test]
503     fn test_atomic_fill_and_borrow() {
504         let lazycell = AtomicLazyCell::new();
505 
506         assert!(!lazycell.filled());
507         lazycell.fill(1).unwrap();
508         assert!(lazycell.filled());
509 
510         let value = lazycell.borrow();
511         assert_eq!(value, Some(&1));
512 
513         let value = lazycell.get();
514         assert_eq!(value, Some(1));
515     }
516 
517     #[test]
518     fn test_atomic_already_filled_panic() {
519         let lazycell = AtomicLazyCell::new();
520 
521         lazycell.fill(1).unwrap();
522         assert_eq!(1, lazycell.fill(1).unwrap_err());
523     }
524 
525     #[test]
526     fn test_atomic_into_inner() {
527         let lazycell = AtomicLazyCell::new();
528 
529         lazycell.fill(1).unwrap();
530         let value = lazycell.into_inner();
531         assert_eq!(value, Some(1));
532     }
533 
534     #[test]
535     fn normal_replace() {
536         let mut cell = LazyCell::new();
537         assert_eq!(cell.fill(1), Ok(()));
538         assert_eq!(cell.replace(2), Some(1));
539         assert_eq!(cell.replace(3), Some(2));
540         assert_eq!(cell.borrow(), Some(&3));
541 
542         let mut cell = LazyCell::new();
543         assert_eq!(cell.replace(2), None);
544     }
545 
546     #[test]
547     fn atomic_replace() {
548         let mut cell = AtomicLazyCell::new();
549         assert_eq!(cell.fill(1), Ok(()));
550         assert_eq!(cell.replace(2), Some(1));
551         assert_eq!(cell.replace(3), Some(2));
552         assert_eq!(cell.borrow(), Some(&3));
553     }
554 }
555