Skip to content

Commit

Permalink
feat: Implement Clone for LazyCell and AtomicLazyCell
Browse files Browse the repository at this point in the history
  • Loading branch information
David Halperin authored and indiv0 committed Dec 3, 2018
1 parent f63f7b7 commit 30fe4a8
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 1 deletion.
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ alphabetical order.
* [Nikita Pekin](https://github.com/indiv0)
* [Ossi Herrala](https://github.com/oherrala)
* [Stephen M. Coakley](https://github.com/sagebind)
* [David Halperin](https://github.com/davidhalperin)

[lazycell]: https://github.com/indiv0/lazycell
2 changes: 1 addition & 1 deletion LICENSE-MIT
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Original work Copyright (c) 2014 The Rust Project Developers
Modified work Copyright (c) 2016-2017 Nikita Pekin and lazycell contributors
Modified work Copyright (c) 2016-2018 Nikita Pekin and lazycell contributors

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
Expand Down
66 changes: 66 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,17 @@ impl<T: Copy> LazyCell<T> {
}
}

impl <T: Clone> Clone for LazyCell<T> {
/// Create a clone of this `LazyCell`
///
/// If self has not been initialized, returns an uninitialized `LazyCell`
/// otherwise returns a `LazyCell` already initialized with a clone of the
/// contents of self.
fn clone(&self) -> LazyCell<T> {
LazyCell { inner: UnsafeCell::new(self.borrow().map(Clone::clone) ) }
}
}

// Tracks the AtomicLazyCell inner state
const NONE: usize = 0;
const LOCK: usize = 1;
Expand Down Expand Up @@ -314,6 +325,23 @@ impl<T: Copy> AtomicLazyCell<T> {
}
}

impl<T: Clone> Clone for AtomicLazyCell<T> {
/// Create a clone of this `AtomicLazyCell`
///
/// If self has not been initialized, returns an uninitialized `AtomicLazyCell`
/// otherwise returns an `AtomicLazyCell` already initialized with a clone of the
/// contents of self.
fn clone(&self) -> AtomicLazyCell<T> {
self.borrow().map_or(
Self::NONE,
|v| AtomicLazyCell {
inner: UnsafeCell::new(Some(v.clone())),
state: AtomicUsize::new(SOME),
}
)
}
}

unsafe impl<T: Sync + Send> Sync for AtomicLazyCell<T> {}

unsafe impl<T: Send> Send for AtomicLazyCell<T> {}
Expand Down Expand Up @@ -580,4 +608,42 @@ mod tests {
assert_eq!(cell.replace(3), Some(2));
assert_eq!(cell.borrow(), Some(&3));
}

#[test]
fn clone() {
let mut cell = LazyCell::new();
let clone1 = cell.clone();
assert_eq!(clone1.borrow(), None);
assert_eq!(cell.fill(1), Ok(()));
let mut clone2 = cell.clone();
assert_eq!(clone1.borrow(), None);
assert_eq!(clone2.borrow(), Some(&1));
assert_eq!(cell.replace(2), Some(1));
assert_eq!(clone1.borrow(), None);
assert_eq!(clone2.borrow(), Some(&1));
assert_eq!(clone1.fill(3), Ok(()));
assert_eq!(clone2.replace(4), Some(1));
assert_eq!(clone1.borrow(), Some(&3));
assert_eq!(clone2.borrow(), Some(&4));
assert_eq!(cell.borrow(), Some(&2));
}

#[test]
fn clone_atomic() {
let mut cell = AtomicLazyCell::new();
let clone1 = cell.clone();
assert_eq!(clone1.borrow(), None);
assert_eq!(cell.fill(1), Ok(()));
let mut clone2 = cell.clone();
assert_eq!(clone1.borrow(), None);
assert_eq!(clone2.borrow(), Some(&1));
assert_eq!(cell.replace(2), Some(1));
assert_eq!(clone1.borrow(), None);
assert_eq!(clone2.borrow(), Some(&1));
assert_eq!(clone1.fill(3), Ok(()));
assert_eq!(clone2.replace(4), Some(1));
assert_eq!(clone1.borrow(), Some(&3));
assert_eq!(clone2.borrow(), Some(&4));
assert_eq!(cell.borrow(), Some(&2));
}
}

0 comments on commit 30fe4a8

Please sign in to comment.