Reduce the need for Send + Sync bounds on generics
This commit is contained in:
@@ -5,7 +5,7 @@ use crate::{
|
||||
use anyhow::anyhow;
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use parking_lot::Mutex;
|
||||
use std::{future::Future, sync::Weak};
|
||||
use std::{any::Any, future::Future, sync::Weak};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AsyncAppContext {
|
||||
@@ -14,13 +14,16 @@ pub struct AsyncAppContext {
|
||||
}
|
||||
|
||||
impl Context for AsyncAppContext {
|
||||
type EntityContext<'a, 'w, T: 'static + Send + Sync> = ModelContext<'a, T>;
|
||||
type EntityContext<'a, 'w, T> = ModelContext<'a, T>;
|
||||
type Result<T> = Result<T>;
|
||||
|
||||
fn entity<T: Send + Sync + 'static>(
|
||||
fn entity<T: 'static>(
|
||||
&mut self,
|
||||
build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
|
||||
) -> Self::Result<Handle<T>> {
|
||||
) -> Self::Result<Handle<T>>
|
||||
where
|
||||
T: Any + Send + Sync,
|
||||
{
|
||||
let app = self
|
||||
.app
|
||||
.upgrade()
|
||||
@@ -29,7 +32,7 @@ impl Context for AsyncAppContext {
|
||||
Ok(lock.entity(build_entity))
|
||||
}
|
||||
|
||||
fn update_entity<T: Send + Sync + 'static, R>(
|
||||
fn update_entity<T: 'static, R>(
|
||||
&mut self,
|
||||
handle: &Handle<T>,
|
||||
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
||||
@@ -129,7 +132,7 @@ impl AsyncAppContext {
|
||||
Ok(app_context.run_on_main(f))
|
||||
}
|
||||
|
||||
pub fn has_global<G: 'static + Send + Sync>(&self) -> Result<bool> {
|
||||
pub fn has_global<G: 'static>(&self) -> Result<bool> {
|
||||
let app = self
|
||||
.app
|
||||
.upgrade()
|
||||
@@ -138,10 +141,7 @@ impl AsyncAppContext {
|
||||
Ok(lock.has_global::<G>())
|
||||
}
|
||||
|
||||
pub fn read_global<G: 'static + Send + Sync, R>(
|
||||
&self,
|
||||
read: impl FnOnce(&G, &AppContext) -> R,
|
||||
) -> Result<R> {
|
||||
pub fn read_global<G: 'static, R>(&self, read: impl FnOnce(&G, &AppContext) -> R) -> Result<R> {
|
||||
let app = self
|
||||
.app
|
||||
.upgrade()
|
||||
@@ -150,7 +150,7 @@ impl AsyncAppContext {
|
||||
Ok(read(lock.global(), &lock))
|
||||
}
|
||||
|
||||
pub fn try_read_global<G: 'static + Send + Sync, R>(
|
||||
pub fn try_read_global<G: 'static, R>(
|
||||
&self,
|
||||
read: impl FnOnce(&G, &AppContext) -> R,
|
||||
) -> Option<R> {
|
||||
@@ -159,7 +159,7 @@ impl AsyncAppContext {
|
||||
Some(read(lock.try_global()?, &lock))
|
||||
}
|
||||
|
||||
pub fn update_global<G: 'static + Send + Sync, R>(
|
||||
pub fn update_global<G: 'static, R>(
|
||||
&mut self,
|
||||
update: impl FnOnce(&mut G, &mut AppContext) -> R,
|
||||
) -> Result<R> {
|
||||
@@ -195,7 +195,7 @@ impl AsyncWindowContext {
|
||||
.ok();
|
||||
}
|
||||
|
||||
pub fn read_global<G: 'static + Send + Sync, R>(
|
||||
pub fn read_global<G: 'static, R>(
|
||||
&self,
|
||||
read: impl FnOnce(&G, &WindowContext) -> R,
|
||||
) -> Result<R> {
|
||||
@@ -203,28 +203,34 @@ impl AsyncWindowContext {
|
||||
.read_window(self.window, |cx| read(cx.global(), cx))
|
||||
}
|
||||
|
||||
pub fn update_global<G: 'static + Send + Sync, R>(
|
||||
pub fn update_global<G, R>(
|
||||
&mut self,
|
||||
update: impl FnOnce(&mut G, &mut WindowContext) -> R,
|
||||
) -> Result<R> {
|
||||
) -> Result<R>
|
||||
where
|
||||
G: 'static,
|
||||
{
|
||||
self.app
|
||||
.update_window(self.window, |cx| cx.update_global(update))
|
||||
}
|
||||
}
|
||||
|
||||
impl Context for AsyncWindowContext {
|
||||
type EntityContext<'a, 'w, T: 'static + Send + Sync> = ViewContext<'a, 'w, T>;
|
||||
type EntityContext<'a, 'w, T> = ViewContext<'a, 'w, T>;
|
||||
type Result<T> = Result<T>;
|
||||
|
||||
fn entity<R: Send + Sync + 'static>(
|
||||
fn entity<T>(
|
||||
&mut self,
|
||||
build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, R>) -> R,
|
||||
) -> Result<Handle<R>> {
|
||||
build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
|
||||
) -> Result<Handle<T>>
|
||||
where
|
||||
T: Any + Send + Sync,
|
||||
{
|
||||
self.app
|
||||
.update_window(self.window, |cx| cx.entity(build_entity))
|
||||
}
|
||||
|
||||
fn update_entity<T: Send + Sync + 'static, R>(
|
||||
fn update_entity<T: 'static, R>(
|
||||
&mut self,
|
||||
handle: &Handle<T>,
|
||||
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
||||
@@ -233,3 +239,14 @@ impl Context for AsyncWindowContext {
|
||||
.update_window(self.window, |cx| cx.update_entity(handle, update))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_async_app_context_send_sync() {
|
||||
fn assert_send_sync<T: Send + Sync>() {}
|
||||
assert_send_sync::<AsyncAppContext>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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> {}
|
||||
|
||||
@@ -4,28 +4,29 @@ use crate::{
|
||||
};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use futures::FutureExt;
|
||||
use std::{any::TypeId, future::Future, marker::PhantomData};
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
future::Future,
|
||||
};
|
||||
|
||||
#[derive(Deref, DerefMut)]
|
||||
pub struct ModelContext<'a, T> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
app: Reference<'a, AppContext>,
|
||||
entity_type: PhantomData<T>,
|
||||
entity_id: EntityId,
|
||||
model_state: WeakHandle<T>,
|
||||
}
|
||||
|
||||
impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
||||
pub(crate) fn mutable(app: &'a mut AppContext, entity_id: EntityId) -> Self {
|
||||
impl<'a, T: 'static> ModelContext<'a, T> {
|
||||
pub(crate) fn mutable(app: &'a mut AppContext, model_state: WeakHandle<T>) -> Self {
|
||||
Self {
|
||||
app: Reference::Mutable(app),
|
||||
entity_type: PhantomData,
|
||||
entity_id,
|
||||
model_state,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn entity_id(&self) -> EntityId {
|
||||
self.entity_id
|
||||
self.model_state.entity_id
|
||||
}
|
||||
|
||||
pub fn handle(&self) -> Handle<T> {
|
||||
@@ -35,14 +36,17 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
||||
}
|
||||
|
||||
pub fn weak_handle(&self) -> WeakHandle<T> {
|
||||
self.app.entities.weak_handle(self.entity_id)
|
||||
self.model_state.clone()
|
||||
}
|
||||
|
||||
pub fn observe<E: Send + Sync + 'static>(
|
||||
pub fn observe<T2: 'static>(
|
||||
&mut self,
|
||||
handle: &Handle<E>,
|
||||
on_notify: impl Fn(&mut T, Handle<E>, &mut ModelContext<'_, T>) + Send + Sync + 'static,
|
||||
) -> Subscription {
|
||||
handle: &Handle<T2>,
|
||||
on_notify: impl Fn(&mut T, Handle<T2>, &mut ModelContext<'_, T>) + Send + Sync + 'static,
|
||||
) -> Subscription
|
||||
where
|
||||
T: Any + Send + Sync,
|
||||
{
|
||||
let this = self.weak_handle();
|
||||
let handle = handle.downgrade();
|
||||
self.app.observers.insert(
|
||||
@@ -58,14 +62,17 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn subscribe<E: EventEmitter + Send + Sync + 'static>(
|
||||
pub fn subscribe<E: 'static + EventEmitter>(
|
||||
&mut self,
|
||||
handle: &Handle<E>,
|
||||
on_event: impl Fn(&mut T, Handle<E>, &E::Event, &mut ModelContext<'_, T>)
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
) -> Subscription {
|
||||
) -> Subscription
|
||||
where
|
||||
T: Any + Send + Sync,
|
||||
{
|
||||
let this = self.weak_handle();
|
||||
let handle = handle.downgrade();
|
||||
self.app.event_listeners.insert(
|
||||
@@ -85,9 +92,12 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
||||
pub fn on_release(
|
||||
&mut self,
|
||||
on_release: impl Fn(&mut T, &mut AppContext) + Send + Sync + 'static,
|
||||
) -> Subscription {
|
||||
) -> Subscription
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
self.app.release_listeners.insert(
|
||||
self.entity_id,
|
||||
self.model_state.entity_id,
|
||||
Box::new(move |this, cx| {
|
||||
let this = this.downcast_mut().expect("invalid entity type");
|
||||
on_release(this, cx);
|
||||
@@ -95,11 +105,14 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn observe_release<E: Send + Sync + 'static>(
|
||||
pub fn observe_release<E: 'static>(
|
||||
&mut self,
|
||||
handle: &Handle<E>,
|
||||
on_release: impl Fn(&mut T, &mut E, &mut ModelContext<'_, T>) + Send + Sync + 'static,
|
||||
) -> Subscription {
|
||||
) -> Subscription
|
||||
where
|
||||
T: Any + Send + Sync,
|
||||
{
|
||||
let this = self.weak_handle();
|
||||
self.app.release_listeners.insert(
|
||||
handle.entity_id,
|
||||
@@ -115,7 +128,10 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
||||
pub fn observe_global<G: 'static>(
|
||||
&mut self,
|
||||
f: impl Fn(&mut T, &mut ModelContext<'_, T>) + Send + Sync + 'static,
|
||||
) -> Subscription {
|
||||
) -> Subscription
|
||||
where
|
||||
T: Any + Send + Sync,
|
||||
{
|
||||
let handle = self.weak_handle();
|
||||
self.global_observers.insert(
|
||||
TypeId::of::<G>(),
|
||||
@@ -129,6 +145,7 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
||||
) -> Subscription
|
||||
where
|
||||
Fut: 'static + Future<Output = ()> + Send,
|
||||
T: Any + Send + Sync,
|
||||
{
|
||||
let handle = self.weak_handle();
|
||||
self.app.quit_observers.insert(
|
||||
@@ -146,9 +163,13 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
||||
}
|
||||
|
||||
pub fn notify(&mut self) {
|
||||
if self.app.pending_notifications.insert(self.entity_id) {
|
||||
if self
|
||||
.app
|
||||
.pending_notifications
|
||||
.insert(self.model_state.entity_id)
|
||||
{
|
||||
self.app.pending_effects.push_back(Effect::Notify {
|
||||
emitter: self.entity_id,
|
||||
emitter: self.model_state.entity_id,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -158,8 +179,8 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
||||
G: 'static + Send + Sync,
|
||||
{
|
||||
let mut global = self.app.lease_global::<G>();
|
||||
let result = f(global.as_mut(), self);
|
||||
self.app.restore_global(global);
|
||||
let result = f(&mut global, self);
|
||||
self.app.end_global_lease(global);
|
||||
result
|
||||
}
|
||||
|
||||
@@ -168,6 +189,7 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
||||
f: impl FnOnce(WeakHandle<T>, AsyncAppContext) -> Fut + Send + 'static,
|
||||
) -> Task<R>
|
||||
where
|
||||
T: 'static,
|
||||
Fut: Future<Output = R> + Send + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
@@ -176,27 +198,34 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: EventEmitter + Send + Sync + 'static> ModelContext<'a, T> {
|
||||
impl<'a, T> ModelContext<'a, T>
|
||||
where
|
||||
T: EventEmitter,
|
||||
T::Event: Send + Sync,
|
||||
{
|
||||
pub fn emit(&mut self, event: T::Event) {
|
||||
self.app.pending_effects.push_back(Effect::Emit {
|
||||
emitter: self.entity_id,
|
||||
emitter: self.model_state.entity_id,
|
||||
event: Box::new(event),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: 'static> Context for ModelContext<'a, T> {
|
||||
type EntityContext<'b, 'c, U: Send + Sync + 'static> = ModelContext<'b, U>;
|
||||
impl<'a, T> Context for ModelContext<'a, T> {
|
||||
type EntityContext<'b, 'c, U> = ModelContext<'b, U>;
|
||||
type Result<U> = U;
|
||||
|
||||
fn entity<U: Send + Sync + 'static>(
|
||||
fn entity<U>(
|
||||
&mut self,
|
||||
build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, U>) -> U,
|
||||
) -> Handle<U> {
|
||||
) -> Handle<U>
|
||||
where
|
||||
U: 'static + Send + Sync,
|
||||
{
|
||||
self.app.entity(build_entity)
|
||||
}
|
||||
|
||||
fn update_entity<U: Send + Sync + 'static, R>(
|
||||
fn update_entity<U: 'static, R>(
|
||||
&mut self,
|
||||
handle: &Handle<U>,
|
||||
update: impl FnOnce(&mut U, &mut Self::EntityContext<'_, '_, U>) -> R,
|
||||
|
||||
Reference in New Issue
Block a user