aboutsummaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs45
1 files changed, 39 insertions, 6 deletions
diff --git a/src/lib.rs b/src/lib.rs
index e753ea8..923d672 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,5 +1,5 @@
// Original work Copyright (c) 2014 The Rust Project Developers
-// Modified work Copyright (c) 2016-2018 Nikita Pekin and the lazycell contributors
+// Modified work Copyright (c) 2016-2020 Nikita Pekin and the lazycell contributors
// See the README.md file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
@@ -44,9 +44,16 @@
//! coordination in a thread-safe fashion. The limitation of an `AtomicLazyCell`
//! is that after it is initialized, it can't be modified.
+
// ANDROID: Unconditionally use std to allow building as a dylib.
+#[cfg(not(test))]
#[macro_use]
extern crate std;
+#[cfg(feature = "serde")]
+extern crate serde;
+
+#[cfg(feature = "serde")]
+mod serde_impl;
use std::cell::UnsafeCell;
use std::mem;
@@ -57,7 +64,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
/// A `LazyCell` is completely frozen once filled, **unless** you have `&mut`
/// access to it, in which case `LazyCell::borrow_mut` may be used to mutate the
/// contents.
-#[derive(Debug, Default)]
+#[derive(Debug)]
pub struct LazyCell<T> {
inner: UnsafeCell<Option<T>>,
}
@@ -70,12 +77,13 @@ impl<T> LazyCell<T> {
/// Put a value into this cell.
///
- /// This function will return `Err(value)` is the cell is already full.
+ /// This function will return `Err(value)` if the cell is already full.
pub fn fill(&self, value: T) -> Result<(), T> {
- let slot = unsafe { &mut *self.inner.get() };
+ let slot = unsafe { &*self.inner.get() };
if slot.is_some() {
return Err(value);
}
+ let slot = unsafe { &mut *self.inner.get() };
*slot = Some(value);
Ok(())
@@ -214,6 +222,12 @@ impl<T: Copy> LazyCell<T> {
}
}
+impl<T> Default for LazyCell<T> {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
impl <T: Clone> Clone for LazyCell<T> {
/// Create a clone of this `LazyCell`
///
@@ -231,7 +245,7 @@ const LOCK: usize = 1;
const SOME: usize = 2;
/// A lazily filled and thread-safe `Cell`, with frozen contents.
-#[derive(Debug, Default)]
+#[derive(Debug)]
pub struct AtomicLazyCell<T> {
inner: UnsafeCell<Option<T>>,
state: AtomicUsize,
@@ -251,7 +265,7 @@ impl<T> AtomicLazyCell<T> {
/// Put a value into this cell.
///
- /// This function will return `Err(value)` is the cell is already full.
+ /// This function will return `Err(value)` if the cell is already full.
pub fn fill(&self, t: T) -> Result<(), T> {
if NONE != self.state.compare_and_swap(NONE, LOCK, Ordering::Acquire) {
return Err(t);
@@ -324,6 +338,12 @@ impl<T: Copy> AtomicLazyCell<T> {
}
}
+impl<T> Default for AtomicLazyCell<T> {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
impl<T: Clone> Clone for AtomicLazyCell<T> {
/// Create a clone of this `AtomicLazyCell`
///
@@ -645,4 +665,17 @@ mod tests {
assert_eq!(clone2.borrow(), Some(&4));
assert_eq!(cell.borrow(), Some(&2));
}
+
+ #[test]
+ fn default() {
+ #[derive(Default)]
+ struct Defaultable;
+ struct NonDefaultable;
+
+ let _: LazyCell<Defaultable> = LazyCell::default();
+ let _: LazyCell<NonDefaultable> = LazyCell::default();
+
+ let _: AtomicLazyCell<Defaultable> = AtomicLazyCell::default();
+ let _: AtomicLazyCell<NonDefaultable> = AtomicLazyCell::default();
+ }
}