mirror of
https://github.com/bevyengine/bevy
synced 2024-11-26 14:40:19 +00:00
Remove unsound cast in thread local resources (#749)
* Remove unsound cast in thread local resources * Make ResourceRef(Mut)::new impossible to cause unsoundness with
This commit is contained in:
parent
1d4a95db62
commit
dea05e9af5
1 changed files with 43 additions and 16 deletions
|
@ -33,7 +33,7 @@ trait ResourceStorage: Downcast {}
|
||||||
impl_downcast!(ResourceStorage);
|
impl_downcast!(ResourceStorage);
|
||||||
|
|
||||||
struct StoredResource<T: 'static> {
|
struct StoredResource<T: 'static> {
|
||||||
value: T,
|
value: std::cell::UnsafeCell<T>,
|
||||||
atomic_borrow: AtomicBorrow,
|
atomic_borrow: AtomicBorrow,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,27 +45,24 @@ impl<T: 'static> VecResourceStorage<T> {
|
||||||
fn get(&self, index: usize) -> Option<ResourceRef<'_, T>> {
|
fn get(&self, index: usize) -> Option<ResourceRef<'_, T>> {
|
||||||
self.stored
|
self.stored
|
||||||
.get(index)
|
.get(index)
|
||||||
.map(|stored| ResourceRef::new(&stored.value, &stored.atomic_borrow))
|
.map(|stored| ResourceRef::new(stored))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_mut(&self, index: usize) -> Option<ResourceRefMut<'_, T>> {
|
fn get_mut(&self, index: usize) -> Option<ResourceRefMut<'_, T>> {
|
||||||
self.stored.get(index).map(|stored|
|
self.stored
|
||||||
// SAFE: ResourceRefMut ensures that this borrow is unique
|
.get(index)
|
||||||
unsafe {
|
.map(|stored| ResourceRefMut::new(stored))
|
||||||
let value = &stored.value as *const T as *mut T;
|
|
||||||
ResourceRefMut::new(&mut *value, &stored.atomic_borrow)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(&mut self, resource: T) {
|
fn push(&mut self, resource: T) {
|
||||||
self.stored.push(StoredResource {
|
self.stored.push(StoredResource {
|
||||||
atomic_borrow: AtomicBorrow::new(),
|
atomic_borrow: AtomicBorrow::new(),
|
||||||
value: resource,
|
value: std::cell::UnsafeCell::new(resource),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set(&mut self, index: usize, resource: T) {
|
fn set(&mut self, index: usize, resource: T) {
|
||||||
self.stored[index].value = resource;
|
self.stored[index].value = std::cell::UnsafeCell::new(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_empty(&self) -> bool {
|
fn is_empty(&self) -> bool {
|
||||||
|
@ -414,9 +411,24 @@ pub struct ResourceRef<'a, T: 'static> {
|
||||||
|
|
||||||
impl<'a, T: 'static> ResourceRef<'a, T> {
|
impl<'a, T: 'static> ResourceRef<'a, T> {
|
||||||
/// Creates a new resource borrow
|
/// Creates a new resource borrow
|
||||||
pub fn new(resource: &'a T, borrow: &'a AtomicBorrow) -> Self {
|
fn new(
|
||||||
borrow.borrow();
|
StoredResource {
|
||||||
Self { resource, borrow }
|
value,
|
||||||
|
atomic_borrow,
|
||||||
|
}: &'a StoredResource<T>,
|
||||||
|
) -> Self {
|
||||||
|
if atomic_borrow.borrow() {
|
||||||
|
Self {
|
||||||
|
// Safe because we acquired the lock
|
||||||
|
resource: unsafe { &*value.get() },
|
||||||
|
borrow: atomic_borrow,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!(
|
||||||
|
"Failed to acquire shared lock on resource: {}",
|
||||||
|
std::any::type_name::<T>()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,9 +466,24 @@ pub struct ResourceRefMut<'a, T: 'static> {
|
||||||
|
|
||||||
impl<'a, T: 'static> ResourceRefMut<'a, T> {
|
impl<'a, T: 'static> ResourceRefMut<'a, T> {
|
||||||
/// Creates a new entity component mutable borrow
|
/// Creates a new entity component mutable borrow
|
||||||
pub fn new(resource: &'a mut T, borrow: &'a AtomicBorrow) -> Self {
|
fn new(
|
||||||
borrow.borrow_mut();
|
StoredResource {
|
||||||
Self { resource, borrow }
|
value,
|
||||||
|
atomic_borrow,
|
||||||
|
}: &'a StoredResource<T>,
|
||||||
|
) -> Self {
|
||||||
|
if atomic_borrow.borrow_mut() {
|
||||||
|
Self {
|
||||||
|
// Safe because we acquired the lock
|
||||||
|
resource: unsafe { &mut *value.get() },
|
||||||
|
borrow: atomic_borrow,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!(
|
||||||
|
"Failed to acquire exclusive lock on resource: {}",
|
||||||
|
std::any::type_name::<T>()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue