fix signals crate

This commit is contained in:
Evan Almloff committed 2023-12-15 18:35:48 -06:00
1 parent 9e388c3c51
commit 6b17d3db1e
11 files changed
+277 -129

No files matched your search

+71 -76
View File
@@ -1,10 +1,7 @@
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
use error::*;
use parking_lot::{Mutex, RwLock};
use references::{GenerationalRefBorrowInfo, GenerationalRefMutBorrowInfo};
use std::any::Any;
use parking_lot::Mutex;
use std::sync::atomic::AtomicU32;
use std::{
fmt::Debug,
@@ -13,7 +10,10 @@ use std::{
sync::Arc,
};
use unsync::UnsyncStorage;
pub use error::*;
pub use references::*;
pub use sync::SyncStorage;
pub use unsync::UnsyncStorage;
mod error;
mod references;
@@ -37,12 +37,12 @@ fn reused() {
let first_ptr;
{
let owner = UnsyncStorage::owner();
first_ptr = owner.insert(1).raw.data.data_ptr();
first_ptr = owner.insert(1).raw.0.data.data_ptr();
drop(owner);
}
{
let owner = UnsyncStorage::owner();
let second_ptr = owner.insert(1234).raw.data.data_ptr();
let second_ptr = owner.insert(1234).raw.0.data.data_ptr();
assert_eq!(first_ptr, second_ptr);
drop(owner);
}
@@ -233,7 +233,7 @@ impl<T: 'static, S: Storage<T>> GenerationalBox<T, S> {
created_at: self.created_at,
}));
}
self.raw.0.data.try_read(
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"))]
@@ -241,7 +241,18 @@ impl<T: 'static, S: Storage<T>> GenerationalBox<T, S> {
borrowed_at: std::panic::Location::caller(),
borrowed_from: &self.raw.0.borrow,
},
)
);
if result.is_ok() {
self.raw
.0
.borrow
.borrowed_at
.write()
.push(std::panic::Location::caller());
}
result
}
/// Read the value. Panics if the value is no longer valid.
@@ -259,14 +270,20 @@ impl<T: 'static, S: Storage<T>> GenerationalBox<T, S> {
created_at: self.created_at,
}));
}
self.raw.0.data.try_write(
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,
},
)
);
if result.is_ok() {
*self.raw.0.borrow.borrowed_mut_at.write() = Some(std::panic::Location::caller());
}
result
}
/// Write the value. Panics if the value is no longer valid.
@@ -296,9 +313,9 @@ impl<T: 'static, S: Storage<T>> GenerationalBox<T, S> {
}
}
impl<T, S: 'static + Copy> Copy for GenerationalBox<T, S> {}
impl<T, S: 'static> Copy for GenerationalBox<T, S> {}
impl<T, S: Copy> Clone for GenerationalBox<T, S> {
impl<T, S> Clone for GenerationalBox<T, S> {
fn clone(&self) -> Self {
*self
}
@@ -384,7 +401,8 @@ pub trait AnyStorage: Default {
}
}
struct MemoryLocation<S: 'static = UnsyncStorage>(&'static MemoryLocationInner<S>);
/// A dynamic memory location that can be used in a generational box.
pub struct MemoryLocation<S: 'static = UnsyncStorage>(&'static MemoryLocationInner<S>);
impl<S: 'static> Clone for MemoryLocation<S> {
fn clone(&self) -> Self {
@@ -397,8 +415,31 @@ impl<S: 'static> Copy for MemoryLocation<S> {}
#[cfg(any(debug_assertions, feature = "debug_borrows"))]
#[derive(Debug, Default)]
struct MemoryLocationBorrowInfo {
borrowed_at: RwLock<Vec<&'static std::panic::Location<'static>>>,
borrowed_mut_at: RwLock<Option<&'static std::panic::Location<'static>>>,
pub(crate) borrowed_at: parking_lot::RwLock<Vec<&'static std::panic::Location<'static>>>,
pub(crate) borrowed_mut_at: parking_lot::RwLock<Option<&'static std::panic::Location<'static>>>,
}
impl MemoryLocationBorrowInfo {
fn borrow_mut_error(&self) -> BorrowMutError {
if let Some(borrowed_mut_at) = self.borrowed_mut_at.read().as_ref() {
BorrowMutError::AlreadyBorrowedMut(crate::error::AlreadyBorrowedMutError {
#[cfg(any(debug_assertions, feature = "debug_borrows"))]
borrowed_mut_at,
})
} else {
BorrowMutError::AlreadyBorrowed(crate::error::AlreadyBorrowedError {
#[cfg(any(debug_assertions, feature = "debug_borrows"))]
borrowed_at: self.borrowed_at.read().clone(),
})
}
}
fn borrow_error(&self) -> BorrowError {
BorrowError::AlreadyBorrowedMut(crate::error::AlreadyBorrowedMutError {
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
borrowed_mut_at: self.borrowed_mut_at.read().unwrap(),
})
}
}
struct MemoryLocationInner<S = UnsyncStorage> {
@@ -444,65 +485,6 @@ impl<S> MemoryLocation<S> {
_marker: PhantomData,
}
}
#[track_caller]
fn try_borrow<T: Any>(
&self,
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
created_at: &'static std::panic::Location<'static>,
) -> std::result::Result<<S as Storage<T>>::Ref, error::BorrowError>
where
S: Storage<T>,
{
match self.0.data.try_read(
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
created_at,
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
GenerationalRefBorrowInfo {
borrowed_at: std::panic::Location::caller(),
borrowed_from: &self.0.borrow,
},
) {
Ok(read) => {
#[cfg(any(debug_assertions, feature = "debug_borrows"))]
self.0
.borrow
.borrowed_at
.write()
.push(std::panic::Location::caller());
Ok(read)
}
Err(err) => Err(err),
}
}
#[track_caller]
fn try_borrow_mut<T: Any>(
&self,
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
created_at: &'static std::panic::Location<'static>,
) -> std::result::Result<<S as Storage<T>>::Mut, error::BorrowMutError>
where
S: Storage<T>,
{
match self.0.data.try_write(
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
created_at,
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
GenerationalRefMutBorrowInfo {
borrowed_from: &self.0.borrow,
},
) {
Ok(read) => {
#[cfg(any(debug_assertions, feature = "debug_borrows"))]
{
*self.0.borrow.borrowed_mut_at.write() = Some(std::panic::Location::caller());
}
Ok(read)
}
Err(err) => Err(err),
}
}
}
/// Owner: Handles dropping generational boxes. The owner acts like a runtime lifetime guard. Any states that you create with an owner will be dropped when that owner is dropped.
@@ -511,7 +493,20 @@ pub struct Owner<S: AnyStorage + 'static = UnsyncStorage> {
phantom: PhantomData<S>,
}
impl<S: AnyStorage + Copy> Owner<S> {
impl<S: AnyStorage> Owner<S> {
/// Insert a value into the store. The value will be dropped when the owner is dropped.
#[track_caller]
pub fn insert<T: 'static>(&self, value: T) -> GenerationalBox<T, S>
where
S: Storage<T>,
{
self.insert_with_caller(
value,
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
std::panic::Location::caller(),
)
}
/// Insert a value into the store with a specific location blamed for creating the value. The value will be dropped when the owner is dropped.
pub fn insert_with_caller<T: 'static>(
&self,
+8 -5
View File
@@ -3,7 +3,7 @@ use std::{
ops::{Deref, DerefMut},
};
use crate::{Mappable, MappableMut, MemoryLocationBorrowInfo};
use crate::{Mappable, MappableMut};
/// A reference to a value in a generational box.
pub struct GenerationalRef<T: 'static, R: Mappable<T>> {
@@ -73,9 +73,10 @@ impl<T: 'static, R: Mappable<T>> Deref for GenerationalRef<T, R> {
}
#[cfg(any(debug_assertions, feature = "debug_borrows"))]
pub(crate) struct GenerationalRefBorrowInfo {
/// Information about a borrow.
pub struct GenerationalRefBorrowInfo {
pub(crate) borrowed_at: &'static std::panic::Location<'static>,
pub(crate) borrowed_from: &'static MemoryLocationBorrowInfo,
pub(crate) borrowed_from: &'static crate::MemoryLocationBorrowInfo,
}
#[cfg(any(debug_assertions, feature = "debug_borrows"))]
@@ -157,8 +158,10 @@ impl<T: 'static, W: MappableMut<T>> DerefMut for GenerationalRefMut<T, W> {
}
#[cfg(any(debug_assertions, feature = "debug_borrows"))]
pub(crate) struct GenerationalRefMutBorrowInfo {
pub(crate) borrowed_from: &'static MemoryLocationBorrowInfo,
/// Information about a mutable borrow.
pub struct GenerationalRefMutBorrowInfo {
/// The location where the borrow occurred.
pub(crate) borrowed_from: &'static crate::MemoryLocationBorrowInfo,
}
#[cfg(any(debug_assertions, feature = "debug_borrows"))]
+15 -8
View File
@@ -5,10 +5,7 @@ use std::sync::{Arc, OnceLock};
use crate::{
error::{self, ValueDroppedError},
references::{
GenerationalRef, GenerationalRefBorrowInfo, GenerationalRefMut,
GenerationalRefMutBorrowInfo,
},
references::{GenerationalRef, GenerationalRefMut},
AnyStorage, Mappable, MappableMut, MemoryLocation, MemoryLocationInner, Storage,
};
@@ -89,9 +86,14 @@ impl<T: Sync + Send + 'static> Storage<T> for SyncStorage {
&'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,
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
at: crate::GenerationalRefBorrowInfo,
) -> Result<Self::Ref, error::BorrowError> {
RwLockReadGuard::try_map(self.0.read(), |any| any.as_ref()?.downcast_ref())
let read = self
.0
.try_read()
.ok_or_else(|| at.borrowed_from.borrow_error())?;
RwLockReadGuard::try_map(read, |any| any.as_ref()?.downcast_ref())
.map_err(|_| {
error::BorrowError::Dropped(ValueDroppedError {
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
@@ -111,9 +113,14 @@ impl<T: Sync + Send + 'static> Storage<T> for SyncStorage {
&'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,
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
at: crate::GenerationalRefMutBorrowInfo,
) -> Result<Self::Mut, error::BorrowMutError> {
RwLockWriteGuard::try_map(self.0.write(), |any| any.as_mut()?.downcast_mut())
let write = self
.0
.try_write()
.ok_or_else(|| at.borrowed_from.borrow_mut_error())?;
RwLockWriteGuard::try_map(write, |any| any.as_mut()?.downcast_mut())
.map_err(|_| {
error::BorrowMutError::Dropped(ValueDroppedError {
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
+21 -14
View File
@@ -1,8 +1,5 @@
use crate::{
references::{
GenerationalRef, GenerationalRefBorrowInfo, GenerationalRefMut,
GenerationalRefMutBorrowInfo,
},
references::{GenerationalRef, GenerationalRefMut},
AnyStorage, Mappable, MappableMut, MemoryLocation, MemoryLocationInner, Storage,
};
use std::cell::{Ref, RefCell, RefMut};
@@ -54,14 +51,19 @@ impl<T: 'static> Storage<T> for UnsyncStorage {
&'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,
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
at: crate::GenerationalRefBorrowInfo,
) -> Result<Self::Ref, crate::error::BorrowError> {
Ref::filter_map(self.0.borrow(), |any| any.as_ref()?.downcast_ref())
let borrow = self
.0
.try_borrow()
.map_err(|_| at.borrowed_from.borrow_error())?;
Ref::filter_map(borrow, |any| any.as_ref()?.downcast_ref())
.map_err(|_| {
crate::error::BorrowError::Dropped(
crate::error::BorrowError::Dropped(crate::error::ValueDroppedError {
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
crate::error::ValueDroppedError { created_at },
)
created_at,
})
})
.map(|guard| {
GenerationalRef::new(
@@ -76,14 +78,19 @@ impl<T: 'static> Storage<T> for UnsyncStorage {
&'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,
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
at: crate::GenerationalRefMutBorrowInfo,
) -> Result<Self::Mut, crate::error::BorrowMutError> {
RefMut::filter_map(self.0.borrow_mut(), |any| any.as_mut()?.downcast_mut())
let borrow = self
.0
.try_borrow_mut()
.map_err(|_| at.borrowed_from.borrow_mut_error())?;
RefMut::filter_map(borrow, |any| any.as_mut()?.downcast_mut())
.map_err(|_| {
crate::error::BorrowMutError::Dropped(
crate::error::BorrowMutError::Dropped(crate::error::ValueDroppedError {
#[cfg(any(debug_assertions, feature = "debug_ownership"))]
crate::error::ValueDroppedError { created_at },
)
created_at,
})
})
.map(|guard| {
GenerationalRefMut::new(