Reduce the need for Send + Sync bounds on generics
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use crate::{AppContext, Context};
|
||||
use crate::{AnyBox, AppContext, Context};
|
||||
use anyhow::{anyhow, Result};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
|
||||
@@ -30,7 +30,7 @@ impl Display for EntityId {
|
||||
}
|
||||
|
||||
pub(crate) struct EntityMap {
|
||||
entities: SecondaryMap<EntityId, Box<dyn Any + Send + Sync>>,
|
||||
entities: SecondaryMap<EntityId, AnyBox>,
|
||||
ref_counts: Arc<RwLock<EntityRefCounts>>,
|
||||
}
|
||||
|
||||
@@ -51,56 +51,46 @@ impl EntityMap {
|
||||
}
|
||||
|
||||
/// Reserve a slot for an entity, which you can subsequently use with `insert`.
|
||||
pub fn reserve<T: 'static + Send + Sync>(&self) -> Slot<T> {
|
||||
pub fn reserve<T: 'static>(&self) -> Slot<T> {
|
||||
let id = self.ref_counts.write().counts.insert(1.into());
|
||||
Slot(Handle::new(id, Arc::downgrade(&self.ref_counts)))
|
||||
}
|
||||
|
||||
/// Insert an entity into a slot obtained by calling `reserve`.
|
||||
pub fn insert<T: 'static + Any + Send + Sync>(
|
||||
&mut self,
|
||||
slot: Slot<T>,
|
||||
entity: T,
|
||||
) -> Handle<T> {
|
||||
pub fn insert<T>(&mut self, slot: Slot<T>, entity: T) -> Handle<T>
|
||||
where
|
||||
T: Any + Send + Sync,
|
||||
{
|
||||
let handle = slot.0;
|
||||
self.entities.insert(handle.entity_id, Box::new(entity));
|
||||
handle
|
||||
}
|
||||
|
||||
/// Move an entity to the stack.
|
||||
pub fn lease<'a, T: 'static + Send + Sync>(&mut self, handle: &'a Handle<T>) -> Lease<'a, T> {
|
||||
pub fn lease<'a, T>(&mut self, handle: &'a Handle<T>) -> Lease<'a, T> {
|
||||
let entity = Some(
|
||||
self.entities
|
||||
.remove(handle.entity_id)
|
||||
.expect("Circular entity lease. Is the entity already being updated?")
|
||||
.downcast::<T>()
|
||||
.unwrap(),
|
||||
.expect("Circular entity lease. Is the entity already being updated?"),
|
||||
);
|
||||
Lease { handle, entity }
|
||||
}
|
||||
|
||||
/// Return an entity after moving it to the stack.
|
||||
pub fn end_lease<T: 'static + Send + Sync>(&mut self, mut lease: Lease<T>) {
|
||||
self.entities
|
||||
.insert(lease.handle.entity_id, lease.entity.take().unwrap());
|
||||
}
|
||||
|
||||
pub fn read<T: 'static + Send + Sync>(&self, handle: &Handle<T>) -> &T {
|
||||
self.entities[handle.entity_id].downcast_ref().unwrap()
|
||||
}
|
||||
|
||||
pub fn weak_handle<T: 'static + Send + Sync>(&self, id: EntityId) -> WeakHandle<T> {
|
||||
WeakHandle {
|
||||
any_handle: AnyWeakHandle {
|
||||
entity_id: id,
|
||||
entity_type: TypeId::of::<T>(),
|
||||
entity_ref_counts: Arc::downgrade(&self.ref_counts),
|
||||
},
|
||||
Lease {
|
||||
handle,
|
||||
entity,
|
||||
entity_type: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take_dropped(&mut self) -> Vec<(EntityId, Box<dyn Any + Send + Sync>)> {
|
||||
/// Return an entity after moving it to the stack.
|
||||
pub fn end_lease<T>(&mut self, mut lease: Lease<T>) {
|
||||
self.entities
|
||||
.insert(lease.handle.entity_id, lease.entity.take().unwrap());
|
||||
}
|
||||
|
||||
pub fn read<T>(&self, handle: &Handle<T>) -> &T {
|
||||
(handle.downcast_entity)(&self.entities[handle.entity_id])
|
||||
}
|
||||
|
||||
pub fn take_dropped(&mut self) -> Vec<(EntityId, AnyBox)> {
|
||||
let dropped_entity_ids = mem::take(&mut self.ref_counts.write().dropped_entity_ids);
|
||||
dropped_entity_ids
|
||||
.into_iter()
|
||||
@@ -109,35 +99,27 @@ impl EntityMap {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Lease<'a, T: Send + Sync> {
|
||||
entity: Option<Box<T>>,
|
||||
pub struct Lease<'a, T> {
|
||||
entity: Option<AnyBox>,
|
||||
pub handle: &'a Handle<T>,
|
||||
entity_type: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'a, T> core::ops::Deref for Lease<'a, T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
impl<'a, T> core::ops::Deref for Lease<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.entity.as_ref().unwrap()
|
||||
(self.handle.downcast_entity)(self.entity.as_ref().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> core::ops::DerefMut for Lease<'a, T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
impl<'a, T> core::ops::DerefMut for Lease<'a, T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.entity.as_mut().unwrap()
|
||||
(self.handle.downcast_entity_mut)(self.entity.as_mut().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Drop for Lease<'a, T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
impl<'a, T> Drop for Lease<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
if self.entity.is_some() {
|
||||
// We don't panic here, because other panics can cause us to drop the lease without ending it cleanly.
|
||||
@@ -147,7 +129,7 @@ where
|
||||
}
|
||||
|
||||
#[derive(Deref, DerefMut)]
|
||||
pub struct Slot<T: Send + Sync + 'static>(Handle<T>);
|
||||
pub struct Slot<T>(Handle<T>);
|
||||
|
||||
pub struct AnyHandle {
|
||||
pub(crate) entity_id: EntityId,
|
||||
@@ -176,14 +158,13 @@ impl AnyHandle {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn downcast<T>(&self) -> Option<Handle<T>>
|
||||
where
|
||||
T: 'static + Send + Sync,
|
||||
{
|
||||
pub fn downcast<T: 'static>(&self) -> Option<Handle<T>> {
|
||||
if TypeId::of::<T>() == self.entity_type {
|
||||
Some(Handle {
|
||||
any_handle: self.clone(),
|
||||
entity_type: PhantomData,
|
||||
downcast_entity: |any| any.downcast_ref().unwrap(),
|
||||
downcast_entity_mut: |any| any.downcast_mut().unwrap(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
@@ -231,10 +212,7 @@ impl Drop for AnyHandle {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Handle<T>> for AnyHandle
|
||||
where
|
||||
T: 'static + Send + Sync,
|
||||
{
|
||||
impl<T> From<Handle<T>> for AnyHandle {
|
||||
fn from(handle: Handle<T>) -> Self {
|
||||
handle.any_handle
|
||||
}
|
||||
@@ -255,18 +233,28 @@ impl PartialEq for AnyHandle {
|
||||
impl Eq for AnyHandle {}
|
||||
|
||||
#[derive(Deref, DerefMut)]
|
||||
pub struct Handle<T: Send + Sync> {
|
||||
pub struct Handle<T> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
any_handle: AnyHandle,
|
||||
entity_type: PhantomData<T>,
|
||||
downcast_entity: fn(&dyn Any) -> &T,
|
||||
downcast_entity_mut: fn(&mut dyn Any) -> &mut T,
|
||||
}
|
||||
|
||||
impl<T: 'static + Send + Sync> Handle<T> {
|
||||
fn new(id: EntityId, entity_map: Weak<RwLock<EntityRefCounts>>) -> Self {
|
||||
unsafe impl<T> Send for Handle<T> {}
|
||||
unsafe impl<T> Sync for Handle<T> {}
|
||||
|
||||
impl<T: 'static> Handle<T> {
|
||||
fn new(id: EntityId, entity_map: Weak<RwLock<EntityRefCounts>>) -> Self
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
Self {
|
||||
any_handle: AnyHandle::new(id, TypeId::of::<T>(), entity_map),
|
||||
entity_type: PhantomData,
|
||||
downcast_entity: |any| any.downcast_ref().unwrap(),
|
||||
downcast_entity_mut: |any| any.downcast_mut().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,6 +262,8 @@ impl<T: 'static + Send + Sync> Handle<T> {
|
||||
WeakHandle {
|
||||
any_handle: self.any_handle.downgrade(),
|
||||
entity_type: self.entity_type,
|
||||
downcast_entity: self.downcast_entity,
|
||||
downcast_entity_mut: self.downcast_entity_mut,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,25 +276,30 @@ impl<T: 'static + Send + Sync> Handle<T> {
|
||||
/// The update function receives a context appropriate for its environment.
|
||||
/// When updating in an `AppContext`, it receives a `ModelContext`.
|
||||
/// When updating an a `WindowContext`, it receives a `ViewContext`.
|
||||
pub fn update<C: Context, R>(
|
||||
pub fn update<C, R>(
|
||||
&self,
|
||||
cx: &mut C,
|
||||
update: impl FnOnce(&mut T, &mut C::EntityContext<'_, '_, T>) -> R,
|
||||
) -> C::Result<R> {
|
||||
) -> C::Result<R>
|
||||
where
|
||||
C: Context,
|
||||
{
|
||||
cx.update_entity(self, update)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync> Clone for Handle<T> {
|
||||
impl<T> Clone for Handle<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
any_handle: self.any_handle.clone(),
|
||||
entity_type: self.entity_type,
|
||||
downcast_entity: self.downcast_entity,
|
||||
downcast_entity_mut: self.downcast_entity_mut,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static + Send + Sync> std::fmt::Debug for Handle<T> {
|
||||
impl<T> std::fmt::Debug for Handle<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
@@ -315,19 +310,19 @@ impl<T: 'static + Send + Sync> std::fmt::Debug for Handle<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + 'static> Hash for Handle<T> {
|
||||
impl<T> Hash for Handle<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.any_handle.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + 'static> PartialEq for Handle<T> {
|
||||
impl<T> PartialEq for Handle<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.any_handle == other.any_handle
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + 'static> Eq for Handle<T> {}
|
||||
impl<T> Eq for Handle<T> {}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AnyWeakHandle {
|
||||
@@ -365,10 +360,7 @@ impl AnyWeakHandle {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<WeakHandle<T>> for AnyWeakHandle
|
||||
where
|
||||
T: 'static + Send + Sync,
|
||||
{
|
||||
impl<T> From<WeakHandle<T>> for AnyWeakHandle {
|
||||
fn from(handle: WeakHandle<T>) -> Self {
|
||||
handle.any_handle
|
||||
}
|
||||
@@ -394,22 +386,31 @@ pub struct WeakHandle<T> {
|
||||
#[deref_mut]
|
||||
any_handle: AnyWeakHandle,
|
||||
entity_type: PhantomData<T>,
|
||||
downcast_entity: fn(&dyn Any) -> &T,
|
||||
pub(crate) downcast_entity_mut: fn(&mut dyn Any) -> &mut T,
|
||||
}
|
||||
|
||||
impl<T: 'static + Send + Sync> Clone for WeakHandle<T> {
|
||||
unsafe impl<T> Send for WeakHandle<T> {}
|
||||
unsafe impl<T> Sync for WeakHandle<T> {}
|
||||
|
||||
impl<T> Clone for WeakHandle<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
any_handle: self.any_handle.clone(),
|
||||
entity_type: self.entity_type,
|
||||
downcast_entity: self.downcast_entity,
|
||||
downcast_entity_mut: self.downcast_entity_mut,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + 'static> WeakHandle<T> {
|
||||
impl<T: 'static> WeakHandle<T> {
|
||||
pub fn upgrade(&self) -> Option<Handle<T>> {
|
||||
Some(Handle {
|
||||
any_handle: self.any_handle.upgrade()?,
|
||||
entity_type: self.entity_type,
|
||||
downcast_entity: self.downcast_entity,
|
||||
downcast_entity_mut: self.downcast_entity_mut,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -420,12 +421,13 @@ impl<T: Send + Sync + 'static> WeakHandle<T> {
|
||||
/// The update function receives a context appropriate for its environment.
|
||||
/// When updating in an `AppContext`, it receives a `ModelContext`.
|
||||
/// When updating an a `WindowContext`, it receives a `ViewContext`.
|
||||
pub fn update<C: Context, R>(
|
||||
pub fn update<C, R>(
|
||||
&self,
|
||||
cx: &mut C,
|
||||
update: impl FnOnce(&mut T, &mut C::EntityContext<'_, '_, T>) -> R,
|
||||
) -> Result<R>
|
||||
where
|
||||
C: Context,
|
||||
Result<C::Result<R>>: crate::Flatten<R>,
|
||||
{
|
||||
crate::Flatten::flatten(
|
||||
@@ -436,16 +438,16 @@ impl<T: Send + Sync + 'static> WeakHandle<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + 'static> Hash for WeakHandle<T> {
|
||||
impl<T> Hash for WeakHandle<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.any_handle.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + 'static> PartialEq for WeakHandle<T> {
|
||||
impl<T> PartialEq for WeakHandle<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.any_handle == other.any_handle
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + 'static> Eq for WeakHandle<T> {}
|
||||
impl<T> Eq for WeakHandle<T> {}
|
||||
|
||||
Reference in New Issue
Block a user