1use std::cell::UnsafeCell;
25use std::mem;
26use std::sync::atomic::{AtomicUsize, Ordering};
27
28#[derive(Debug, Default)]
34pub struct LazyCell<T> {
35 inner: UnsafeCell<Option<T>>,
36}
37
38impl<T> LazyCell<T> {
39 pub fn new() -> LazyCell<T> {
41 LazyCell {
42 inner: UnsafeCell::new(None),
43 }
44 }
45
46 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 #[allow(unused)]
70 pub fn replace(&mut self, value: T) -> Option<T> {
71 unsafe { &mut *self.inner.get() }.replace(value)
72 }
73
74 #[allow(unused)]
76 pub fn filled(&self) -> bool {
77 self.borrow().is_some()
78 }
79
80 #[allow(unused)]
86 pub fn borrow(&self) -> Option<&T> {
87 unsafe { &*self.inner.get() }.as_ref()
88 }
89
90 #[allow(unused)]
96 pub fn borrow_mut(&mut self) -> Option<&mut T> {
97 unsafe { &mut *self.inner.get() }.as_mut()
98 }
99
100 #[allow(unused)]
110 pub fn borrow_with<F: FnOnce() -> T>(&self, f: F) -> &T {
111 if let Some(value) = self.borrow() {
112 return value;
113 }
114 let value = f();
115 if self.fill(value).is_err() {
116 panic!("borrow_with: cell was filled by closure")
117 }
118 self.borrow().unwrap()
119 }
120
121 #[allow(unused)]
131 pub fn borrow_mut_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
132 if !self.filled() {
133 let value = f();
134 if self.fill(value).is_err() {
135 panic!("borrow_mut_with: cell was filled by closure")
136 }
137 }
138
139 self.borrow_mut().unwrap()
140 }
141
142 #[allow(unused)]
148 pub fn try_borrow_with<E, F>(&self, f: F) -> Result<&T, E>
149 where
150 F: FnOnce() -> Result<T, E>,
151 {
152 if let Some(value) = self.borrow() {
153 return Ok(value);
154 }
155 let value = f()?;
156 if self.fill(value).is_err() {
157 panic!("try_borrow_with: cell was filled by closure")
158 }
159 Ok(self.borrow().unwrap())
160 }
161
162 #[allow(unused)]
168 pub fn try_borrow_mut_with<E, F>(&mut self, f: F) -> Result<&mut T, E>
169 where
170 F: FnOnce() -> Result<T, E>,
171 {
172 if self.filled() {
173 return Ok(self.borrow_mut().unwrap());
174 }
175 let value = f()?;
176 if self.fill(value).is_err() {
177 panic!("try_borrow_mut_with: cell was filled by closure")
178 }
179 Ok(self.borrow_mut().unwrap())
180 }
181
182 #[allow(unused)]
184 pub fn into_inner(self) -> Option<T> {
185 #[allow(unused_unsafe)]
189 unsafe {
190 self.inner.into_inner()
191 }
192 }
193}
194
195impl<T: Copy> LazyCell<T> {
196 #[allow(unused)]
201 pub fn get(&self) -> Option<T> {
202 unsafe { *self.inner.get() }
203 }
204}
205
206const NONE: usize = 0;
208const LOCK: usize = 1;
209const SOME: usize = 2;
210
211#[derive(Debug, Default)]
213pub struct AtomicLazyCell<T> {
214 inner: UnsafeCell<Option<T>>,
215 state: AtomicUsize,
216}
217
218impl<T> AtomicLazyCell<T> {
219 pub fn new() -> AtomicLazyCell<T> {
221 Self {
222 inner: UnsafeCell::new(None),
223 state: AtomicUsize::new(NONE),
224 }
225 }
226
227 pub fn fill(&self, t: T) -> Result<(), T> {
231 #[allow(deprecated)]
232 if NONE != self.state.compare_and_swap(NONE, LOCK, Ordering::Acquire) {
233 return Err(t);
234 }
235
236 unsafe { *self.inner.get() = Some(t) };
237
238 #[allow(deprecated)]
239 if LOCK != self.state.compare_and_swap(LOCK, SOME, Ordering::Release) {
240 panic!("unable to release lock");
241 }
242
243 Ok(())
244 }
245
246 #[allow(unused)]
257 pub fn replace(&mut self, value: T) -> Option<T> {
258 match mem::replace(self.state.get_mut(), SOME) {
259 NONE | SOME => {}
260 _ => panic!("cell in inconsistent state"),
261 }
262 unsafe { &mut *self.inner.get() }.replace(value)
263 }
264
265 #[allow(unused)]
267 pub fn filled(&self) -> bool {
268 self.state.load(Ordering::Acquire) == SOME
269 }
270
271 pub fn borrow(&self) -> Option<&T> {
277 match self.state.load(Ordering::Acquire) {
278 SOME => unsafe { &*self.inner.get() }.as_ref(),
279 _ => None,
280 }
281 }
282
283 #[allow(unused)]
285 pub fn into_inner(self) -> Option<T> {
286 #[allow(unused_unsafe)]
290 unsafe {
291 self.inner.into_inner()
292 }
293 }
294}
295
296impl<T: Copy> AtomicLazyCell<T> {
297 #[allow(unused)]
302 pub fn get(&self) -> Option<T> {
303 match self.state.load(Ordering::Acquire) {
304 SOME => unsafe { *self.inner.get() },
305 _ => None,
306 }
307 }
308}
309
310unsafe impl<T: Sync + Send> Sync for AtomicLazyCell<T> {}
311
312unsafe impl<T: Send> Send for AtomicLazyCell<T> {}
313
314#[cfg(test)]
315mod tests {
316 use super::{AtomicLazyCell, LazyCell};
317
318 #[test]
319 fn test_borrow_from_empty() {
320 let lazycell: LazyCell<usize> = LazyCell::new();
321
322 let value = lazycell.borrow();
323 assert_eq!(value, None);
324
325 let value = lazycell.get();
326 assert_eq!(value, None);
327 }
328
329 #[test]
330 fn test_fill_and_borrow() {
331 let lazycell = LazyCell::new();
332
333 assert!(!lazycell.filled());
334 lazycell.fill(1).unwrap();
335 assert!(lazycell.filled());
336
337 let value = lazycell.borrow();
338 assert_eq!(value, Some(&1));
339
340 let value = lazycell.get();
341 assert_eq!(value, Some(1));
342 }
343
344 #[test]
345 fn test_borrow_mut() {
346 let mut lazycell = LazyCell::new();
347 assert!(lazycell.borrow_mut().is_none());
348
349 lazycell.fill(1).unwrap();
350 assert_eq!(lazycell.borrow_mut(), Some(&mut 1));
351
352 *lazycell.borrow_mut().unwrap() = 2;
353 assert_eq!(lazycell.borrow_mut(), Some(&mut 2));
354
355 lazycell = LazyCell::new();
357 assert!(lazycell.borrow_mut().is_none());
358 }
359
360 #[test]
361 fn test_already_filled_error() {
362 let lazycell = LazyCell::new();
363
364 lazycell.fill(1).unwrap();
365 assert_eq!(lazycell.fill(1), Err(1));
366 }
367
368 #[test]
369 fn test_borrow_with() {
370 let lazycell = LazyCell::new();
371
372 let value = lazycell.borrow_with(|| 1);
373 assert_eq!(&1, value);
374 }
375
376 #[test]
377 fn test_borrow_with_already_filled() {
378 let lazycell = LazyCell::new();
379 lazycell.fill(1).unwrap();
380
381 let value = lazycell.borrow_with(|| 1);
382 assert_eq!(&1, value);
383 }
384
385 #[test]
386 fn test_borrow_with_not_called_when_filled() {
387 let lazycell = LazyCell::new();
388
389 lazycell.fill(1).unwrap();
390
391 let value = lazycell.borrow_with(|| 2);
392 assert_eq!(&1, value);
393 }
394
395 #[test]
396 #[should_panic]
397 fn test_borrow_with_sound_with_reentrancy() {
398 let lazycell: LazyCell<Box<i32>> = LazyCell::new();
401
402 let mut reference: Option<&i32> = None;
403
404 lazycell.borrow_with(|| {
405 let _ = lazycell.fill(Box::new(1));
406 reference = lazycell.borrow().map(|r| &**r);
407 Box::new(2)
408 });
409 }
410
411 #[test]
412 fn test_borrow_mut_with() {
413 let mut lazycell = LazyCell::new();
414
415 {
416 let value = lazycell.borrow_mut_with(|| 1);
417 assert_eq!(&mut 1, value);
418 *value = 2;
419 }
420 assert_eq!(&2, lazycell.borrow().unwrap());
421 }
422
423 #[test]
424 fn test_borrow_mut_with_already_filled() {
425 let mut lazycell = LazyCell::new();
426 lazycell.fill(1).unwrap();
427
428 let value = lazycell.borrow_mut_with(|| 1);
429 assert_eq!(&1, value);
430 }
431
432 #[test]
433 fn test_borrow_mut_with_not_called_when_filled() {
434 let mut lazycell = LazyCell::new();
435
436 lazycell.fill(1).unwrap();
437
438 let value = lazycell.borrow_mut_with(|| 2);
439 assert_eq!(&1, value);
440 }
441
442 #[test]
443 fn test_try_borrow_with_ok() {
444 let lazycell = LazyCell::new();
445 let result = lazycell.try_borrow_with::<(), _>(|| Ok(1));
446 assert_eq!(result, Ok(&1));
447 }
448
449 #[test]
450 fn test_try_borrow_with_err() {
451 let lazycell = LazyCell::<()>::new();
452 let result = lazycell.try_borrow_with(|| Err(1));
453 assert_eq!(result, Err(1));
454 }
455
456 #[test]
457 fn test_try_borrow_with_already_filled() {
458 let lazycell = LazyCell::new();
459 lazycell.fill(1).unwrap();
460 let result = lazycell.try_borrow_with::<(), _>(|| unreachable!());
461 assert_eq!(result, Ok(&1));
462 }
463
464 #[test]
465 #[should_panic]
466 fn test_try_borrow_with_sound_with_reentrancy() {
467 let lazycell: LazyCell<Box<i32>> = LazyCell::new();
468
469 let mut reference: Option<&i32> = None;
470
471 let _ = lazycell.try_borrow_with::<(), _>(|| {
472 let _ = lazycell.fill(Box::new(1));
473 reference = lazycell.borrow().map(|r| &**r);
474 Ok(Box::new(2))
475 });
476 }
477
478 #[test]
479 fn test_try_borrow_mut_with_ok() {
480 let mut lazycell = LazyCell::new();
481 {
482 let result = lazycell.try_borrow_mut_with::<(), _>(|| Ok(1));
483 assert_eq!(result, Ok(&mut 1));
484 *result.unwrap() = 2;
485 }
486 assert_eq!(&mut 2, lazycell.borrow().unwrap());
487 }
488
489 #[test]
490 fn test_try_borrow_mut_with_err() {
491 let mut lazycell = LazyCell::<()>::new();
492 let result = lazycell.try_borrow_mut_with(|| Err(1));
493 assert_eq!(result, Err(1));
494 }
495
496 #[test]
497 fn test_try_borrow_mut_with_already_filled() {
498 let mut lazycell = LazyCell::new();
499 lazycell.fill(1).unwrap();
500 let result = lazycell.try_borrow_mut_with::<(), _>(|| unreachable!());
501 assert_eq!(result, Ok(&mut 1));
502 }
503
504 #[test]
505 fn test_into_inner() {
506 let lazycell = LazyCell::new();
507
508 lazycell.fill(1).unwrap();
509 let value = lazycell.into_inner();
510 assert_eq!(value, Some(1));
511 }
512
513 #[test]
514 fn test_atomic_borrow_from_empty() {
515 let lazycell: AtomicLazyCell<usize> = AtomicLazyCell::new();
516
517 let value = lazycell.borrow();
518 assert_eq!(value, None);
519
520 let value = lazycell.get();
521 assert_eq!(value, None);
522 }
523
524 #[test]
525 fn test_atomic_fill_and_borrow() {
526 let lazycell = AtomicLazyCell::new();
527
528 assert!(!lazycell.filled());
529 lazycell.fill(1).unwrap();
530 assert!(lazycell.filled());
531
532 let value = lazycell.borrow();
533 assert_eq!(value, Some(&1));
534
535 let value = lazycell.get();
536 assert_eq!(value, Some(1));
537 }
538
539 #[test]
540 fn test_atomic_already_filled_panic() {
541 let lazycell = AtomicLazyCell::new();
542
543 lazycell.fill(1).unwrap();
544 assert_eq!(1, lazycell.fill(1).unwrap_err());
545 }
546
547 #[test]
548 fn test_atomic_into_inner() {
549 let lazycell = AtomicLazyCell::new();
550
551 lazycell.fill(1).unwrap();
552 let value = lazycell.into_inner();
553 assert_eq!(value, Some(1));
554 }
555
556 #[test]
557 fn normal_replace() {
558 let mut cell = LazyCell::new();
559 assert_eq!(cell.fill(1), Ok(()));
560 assert_eq!(cell.replace(2), Some(1));
561 assert_eq!(cell.replace(3), Some(2));
562 assert_eq!(cell.borrow(), Some(&3));
563
564 let mut cell = LazyCell::new();
565 assert_eq!(cell.replace(2), None);
566 }
567
568 #[test]
569 fn atomic_replace() {
570 let mut cell = AtomicLazyCell::new();
571 assert_eq!(cell.fill(1), Ok(()));
572 assert_eq!(cell.replace(2), Some(1));
573 assert_eq!(cell.replace(3), Some(2));
574 assert_eq!(cell.borrow(), Some(&3));
575 }
576}