|
@@ -20,138 +20,6 @@ mod references;
|
|
|
mod sync;
|
|
|
mod unsync;
|
|
|
|
|
|
-/// # Example
|
|
|
-///
|
|
|
-/// ```compile_fail
|
|
|
-/// let data = String::from("hello world");
|
|
|
-/// let owner = UnsyncStorage::owner();
|
|
|
-/// let key = owner.insert(&data);
|
|
|
-/// drop(data);
|
|
|
-/// assert_eq!(*key.read(), "hello world");
|
|
|
-/// ```
|
|
|
-#[allow(unused)]
|
|
|
-fn compile_fail() {}
|
|
|
-
|
|
|
-#[test]
|
|
|
-fn reused() {
|
|
|
- let first_ptr;
|
|
|
- {
|
|
|
- let owner = UnsyncStorage::owner();
|
|
|
- first_ptr = owner.insert(1).raw.0.data.data_ptr();
|
|
|
- drop(owner);
|
|
|
- }
|
|
|
- {
|
|
|
- let owner = UnsyncStorage::owner();
|
|
|
- let second_ptr = owner.insert(1234).raw.0.data.data_ptr();
|
|
|
- assert_eq!(first_ptr, second_ptr);
|
|
|
- drop(owner);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#[test]
|
|
|
-fn leaking_is_ok() {
|
|
|
- let data = String::from("hello world");
|
|
|
- let key;
|
|
|
- {
|
|
|
- // create an owner
|
|
|
- let owner = UnsyncStorage::owner();
|
|
|
- // insert data into the store
|
|
|
- key = owner.insert(data);
|
|
|
- // don't drop the owner
|
|
|
- std::mem::forget(owner);
|
|
|
- }
|
|
|
- assert_eq!(
|
|
|
- key.try_read().as_deref().unwrap(),
|
|
|
- &"hello world".to_string()
|
|
|
- );
|
|
|
-}
|
|
|
-
|
|
|
-#[test]
|
|
|
-fn drops() {
|
|
|
- let data = String::from("hello world");
|
|
|
- let key;
|
|
|
- {
|
|
|
- // create an owner
|
|
|
- let owner = UnsyncStorage::owner();
|
|
|
- // insert data into the store
|
|
|
- key = owner.insert(data);
|
|
|
- // drop the owner
|
|
|
- }
|
|
|
- assert!(key.try_read().is_err());
|
|
|
-}
|
|
|
-
|
|
|
-#[test]
|
|
|
-fn works() {
|
|
|
- let owner = UnsyncStorage::owner();
|
|
|
- let key = owner.insert(1);
|
|
|
-
|
|
|
- assert_eq!(*key.read(), 1);
|
|
|
-}
|
|
|
-
|
|
|
-#[test]
|
|
|
-fn insert_while_reading() {
|
|
|
- let owner = UnsyncStorage::owner();
|
|
|
- let key;
|
|
|
- {
|
|
|
- let data: String = "hello world".to_string();
|
|
|
- key = owner.insert(data);
|
|
|
- }
|
|
|
- let value = key.read();
|
|
|
- owner.insert(&1);
|
|
|
- assert_eq!(*value, "hello world");
|
|
|
-}
|
|
|
-
|
|
|
-#[test]
|
|
|
-#[should_panic]
|
|
|
-fn panics() {
|
|
|
- let owner = UnsyncStorage::owner();
|
|
|
- let key = owner.insert(1);
|
|
|
- drop(owner);
|
|
|
-
|
|
|
- assert_eq!(*key.read(), 1);
|
|
|
-}
|
|
|
-
|
|
|
-#[test]
|
|
|
-fn fuzz() {
|
|
|
- fn maybe_owner_scope(
|
|
|
- valid_keys: &mut Vec<GenerationalBox<String>>,
|
|
|
- invalid_keys: &mut Vec<GenerationalBox<String>>,
|
|
|
- path: &mut Vec<u8>,
|
|
|
- ) {
|
|
|
- let branch_cutoff = 5;
|
|
|
- let children = if path.len() < branch_cutoff {
|
|
|
- rand::random::<u8>() % 4
|
|
|
- } else {
|
|
|
- rand::random::<u8>() % 2
|
|
|
- };
|
|
|
-
|
|
|
- for i in 0..children {
|
|
|
- let owner = UnsyncStorage::owner();
|
|
|
- let key = owner.insert(format!("hello world {path:?}"));
|
|
|
- valid_keys.push(key);
|
|
|
- path.push(i);
|
|
|
- // read all keys
|
|
|
- println!("{:?}", path);
|
|
|
- for key in valid_keys.iter() {
|
|
|
- let value = key.read();
|
|
|
- println!("{:?}", &*value);
|
|
|
- assert!(value.starts_with("hello world"));
|
|
|
- }
|
|
|
- #[cfg(any(debug_assertions, feature = "check_generation"))]
|
|
|
- for key in invalid_keys.iter() {
|
|
|
- assert!(!key.validate());
|
|
|
- }
|
|
|
- maybe_owner_scope(valid_keys, invalid_keys, path);
|
|
|
- invalid_keys.push(valid_keys.pop().unwrap());
|
|
|
- path.pop();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for _ in 0..10 {
|
|
|
- maybe_owner_scope(&mut Vec::new(), &mut Vec::new(), &mut Vec::new());
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
/// The type erased id of a generational box.
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
pub struct GenerationalBoxId {
|
|
@@ -200,7 +68,7 @@ impl<T: 'static, S: AnyStorage> Debug for GenerationalBox<T, S> {
|
|
|
|
|
|
impl<T: 'static, S: Storage<T>> GenerationalBox<T, S> {
|
|
|
#[inline(always)]
|
|
|
- fn validate(&self) -> bool {
|
|
|
+ pub fn validate(&self) -> bool {
|
|
|
#[cfg(any(debug_assertions, feature = "check_generation"))]
|
|
|
{
|
|
|
self.raw
|
|
@@ -215,6 +83,11 @@ impl<T: 'static, S: Storage<T>> GenerationalBox<T, S> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// Get the raw pointer to the value.
|
|
|
+ pub fn raw_ptr(&self) -> *const () {
|
|
|
+ self.raw.0.data.data_ptr()
|
|
|
+ }
|
|
|
+
|
|
|
/// Get the id of the generational box.
|
|
|
pub fn id(&self) -> GenerationalBoxId {
|
|
|
GenerationalBoxId {
|
|
@@ -234,12 +107,11 @@ impl<T: 'static, S: Storage<T>> GenerationalBox<T, S> {
|
|
|
}));
|
|
|
}
|
|
|
let result = self.raw.0.data.try_read(
|
|
|
- #[cfg(any(debug_assertions, feature = "debug_ownership"))]
|
|
|
- self.created_at,
|
|
|
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
|
|
|
GenerationalRefBorrowInfo {
|
|
|
borrowed_at: std::panic::Location::caller(),
|
|
|
borrowed_from: &self.raw.0.borrow,
|
|
|
+ created_at: self.created_at,
|
|
|
},
|
|
|
);
|
|
|
|
|
@@ -272,11 +144,10 @@ impl<T: 'static, S: Storage<T>> GenerationalBox<T, S> {
|
|
|
}));
|
|
|
}
|
|
|
let result = self.raw.0.data.try_write(
|
|
|
- #[cfg(any(debug_assertions, feature = "debug_ownership"))]
|
|
|
- self.created_at,
|
|
|
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
|
|
|
GenerationalRefMutBorrowInfo {
|
|
|
borrowed_from: &self.raw.0.borrow,
|
|
|
+ created_at: self.created_at,
|
|
|
},
|
|
|
);
|
|
|
|
|
@@ -360,16 +231,12 @@ pub trait Storage<Data = ()>: AnyStorage + 'static {
|
|
|
/// Try to read the value. Returns None if the value is no longer valid.
|
|
|
fn try_read(
|
|
|
&'static self,
|
|
|
- #[cfg(any(debug_assertions, feature = "debug_ownership"))]
|
|
|
- created_at: &'static std::panic::Location<'static>,
|
|
|
#[cfg(any(debug_assertions, feature = "debug_ownership"))] at: GenerationalRefBorrowInfo,
|
|
|
) -> Result<Self::Ref<Data>, BorrowError>;
|
|
|
|
|
|
/// Try to write the value. Returns None if the value is no longer valid.
|
|
|
fn try_write(
|
|
|
&'static self,
|
|
|
- #[cfg(any(debug_assertions, feature = "debug_ownership"))]
|
|
|
- created_at: &'static std::panic::Location<'static>,
|
|
|
#[cfg(any(debug_assertions, feature = "debug_ownership"))] at: GenerationalRefMutBorrowInfo,
|
|
|
) -> Result<Self::Mut<Data>, BorrowMutError>;
|
|
|
|
|
@@ -444,8 +311,10 @@ impl MemoryLocationBorrowInfo {
|
|
|
|
|
|
struct MemoryLocationInner<S = UnsyncStorage> {
|
|
|
data: S,
|
|
|
+
|
|
|
#[cfg(any(debug_assertions, feature = "check_generation"))]
|
|
|
generation: AtomicU32,
|
|
|
+
|
|
|
#[cfg(any(debug_assertions, feature = "debug_borrows"))]
|
|
|
borrow: MemoryLocationBorrowInfo,
|
|
|
}
|