Checkpoint
This commit is contained in:
parent
13ba450c4c
commit
5ab1034698
5 changed files with 63 additions and 32 deletions
|
@ -1,9 +1,9 @@
|
||||||
mod async_context;
|
mod async_context;
|
||||||
mod entities;
|
mod entity_map;
|
||||||
mod model_context;
|
mod model_context;
|
||||||
|
|
||||||
pub use async_context::*;
|
pub use async_context::*;
|
||||||
pub use entities::*;
|
pub use entity_map::*;
|
||||||
pub use model_context::*;
|
pub use model_context::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
@ -1,9 +1,16 @@
|
||||||
use crate::Context;
|
use crate::Context;
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use derive_more::{Deref, DerefMut};
|
use derive_more::{Deref, DerefMut};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::{Mutex, RwLock};
|
||||||
use slotmap::{SecondaryMap, SlotMap};
|
use slotmap::{SecondaryMap, SlotMap};
|
||||||
use std::{any::Any, marker::PhantomData, sync::Arc};
|
use std::{
|
||||||
|
any::Any,
|
||||||
|
marker::PhantomData,
|
||||||
|
sync::{
|
||||||
|
atomic::{AtomicUsize, Ordering::SeqCst},
|
||||||
|
Arc, Weak,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
slotmap::new_key_type! { pub struct EntityId; }
|
slotmap::new_key_type! { pub struct EntityId; }
|
||||||
|
|
||||||
|
@ -16,24 +23,21 @@ pub struct Lease<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct EntityMap {
|
pub(crate) struct EntityMap {
|
||||||
ref_counts: Arc<Mutex<SlotMap<EntityId, usize>>>,
|
ref_counts: Arc<RwLock<RefCounts>>,
|
||||||
entities: Arc<Mutex<SecondaryMap<EntityId, Box<dyn Any + Send + Sync>>>>,
|
entities: Arc<Mutex<SecondaryMap<EntityId, Box<dyn Any + Send + Sync>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EntityMap {
|
impl EntityMap {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
ref_counts: Arc::new(Mutex::new(SlotMap::with_key())),
|
ref_counts: Arc::new(RwLock::new(SlotMap::with_key())),
|
||||||
entities: Arc::new(Mutex::new(SecondaryMap::new())),
|
entities: Arc::new(Mutex::new(SecondaryMap::new())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reserve<T>(&self) -> Slot<T> {
|
pub fn reserve<T: 'static + Send + Sync>(&self) -> Slot<T> {
|
||||||
let id = self.ref_counts.lock().insert(1);
|
let id = self.ref_counts.write().insert(1.into());
|
||||||
Slot(Handle {
|
Slot(Handle::new(id, Arc::downgrade(&self.ref_counts)))
|
||||||
id,
|
|
||||||
entity_type: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn redeem<T: 'static + Any + Send + Sync>(&self, slot: Slot<T>, entity: T) -> Handle<T> {
|
pub fn redeem<T: 'static + Any + Send + Sync>(&self, slot: Slot<T>, entity: T) -> Handle<T> {
|
||||||
|
@ -42,7 +46,7 @@ impl EntityMap {
|
||||||
handle
|
handle
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lease<T: 'static>(&self, handle: &Handle<T>) -> Lease<T> {
|
pub fn lease<T: 'static + Send + Sync>(&self, handle: &Handle<T>) -> Lease<T> {
|
||||||
let id = handle.id;
|
let id = handle.id;
|
||||||
let entity = self
|
let entity = self
|
||||||
.entities
|
.entities
|
||||||
|
@ -57,21 +61,33 @@ impl EntityMap {
|
||||||
pub fn end_lease<T: 'static + Send + Sync>(&mut self, lease: Lease<T>) {
|
pub fn end_lease<T: 'static + Send + Sync>(&mut self, lease: Lease<T>) {
|
||||||
self.entities.lock().insert(lease.id, lease.entity);
|
self.entities.lock().insert(lease.id, lease.entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn weak_handle<T: 'static + Send + Sync>(&self, id: EntityId) -> WeakHandle<T> {
|
||||||
|
WeakHandle {
|
||||||
|
id,
|
||||||
|
entity_type: PhantomData,
|
||||||
|
ref_counts: Arc::downgrade(&self.ref_counts),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deref, DerefMut)]
|
#[derive(Deref, DerefMut)]
|
||||||
pub struct Slot<T>(Handle<T>);
|
pub struct Slot<T: Send + Sync + 'static>(Handle<T>);
|
||||||
|
|
||||||
pub struct Handle<T> {
|
pub struct Handle<T: Send + Sync> {
|
||||||
pub(crate) id: EntityId,
|
pub(crate) id: EntityId,
|
||||||
pub(crate) entity_type: PhantomData<T>,
|
entity_type: PhantomData<T>,
|
||||||
|
ref_counts: Weak<RwLock<RefCounts>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Send + Sync + 'static> Handle<T> {
|
type RefCounts = SlotMap<EntityId, AtomicUsize>;
|
||||||
pub fn new(id: EntityId) -> Self {
|
|
||||||
|
impl<T: 'static + Send + Sync> Handle<T> {
|
||||||
|
pub fn new(id: EntityId, ref_counts: Weak<RwLock<RefCounts>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
entity_type: PhantomData,
|
entity_type: PhantomData,
|
||||||
|
ref_counts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +95,7 @@ impl<T: Send + Sync + 'static> Handle<T> {
|
||||||
WeakHandle {
|
WeakHandle {
|
||||||
id: self.id,
|
id: self.id,
|
||||||
entity_type: self.entity_type,
|
entity_type: self.entity_type,
|
||||||
|
ref_counts: self.ref_counts.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,11 +113,23 @@ impl<T: Send + Sync + 'static> Handle<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Clone for Handle<T> {
|
impl<T: Send + Sync> Clone for Handle<T> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: self.id,
|
id: self.id,
|
||||||
entity_type: PhantomData,
|
entity_type: PhantomData,
|
||||||
|
ref_counts: self.ref_counts.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Send + Sync> Drop for Handle<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Some(ref_counts) = self.ref_counts.upgrade() {
|
||||||
|
if let Some(count) = ref_counts.read().get(self.id) {
|
||||||
|
let prev_count = count.fetch_sub(1, SeqCst);
|
||||||
|
assert_ne!(prev_count, 0, "Detected over-release of a handle.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,14 +137,17 @@ impl<T> Clone for Handle<T> {
|
||||||
pub struct WeakHandle<T> {
|
pub struct WeakHandle<T> {
|
||||||
pub(crate) id: EntityId,
|
pub(crate) id: EntityId,
|
||||||
pub(crate) entity_type: PhantomData<T>,
|
pub(crate) entity_type: PhantomData<T>,
|
||||||
|
pub(crate) ref_counts: Weak<RwLock<RefCounts>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Send + Sync + 'static> WeakHandle<T> {
|
impl<T: Send + Sync + 'static> WeakHandle<T> {
|
||||||
pub fn upgrade(&self, _: &impl Context) -> Option<Handle<T>> {
|
pub fn upgrade(&self, _: &impl Context) -> Option<Handle<T>> {
|
||||||
// todo!("Actually upgrade")
|
let ref_counts = self.ref_counts.upgrade()?;
|
||||||
|
ref_counts.read().get(self.id).unwrap().fetch_add(1, SeqCst);
|
||||||
Some(Handle {
|
Some(Handle {
|
||||||
id: self.id,
|
id: self.id,
|
||||||
entity_type: self.entity_type,
|
entity_type: self.entity_type,
|
||||||
|
ref_counts: self.ref_counts.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,10 +35,7 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub fn handle(&self) -> WeakHandle<T> {
|
pub fn handle(&self) -> WeakHandle<T> {
|
||||||
WeakHandle {
|
self.app.entities.weak_handle(self.entity_id)
|
||||||
id: self.entity_id,
|
|
||||||
entity_type: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn observe<E: Send + Sync + 'static>(
|
pub fn observe<E: Send + Sync + 'static>(
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use std::{any::Any, marker::PhantomData, sync::Arc};
|
use std::{any::Any, marker::PhantomData, sync::Arc};
|
||||||
|
|
||||||
pub struct View<S, P> {
|
pub struct View<S: Send + Sync, P> {
|
||||||
state: Handle<S>,
|
state: Handle<S>,
|
||||||
render: Arc<dyn Fn(&mut S, &mut ViewContext<S>) -> AnyElement<S> + Send + Sync + 'static>,
|
render: Arc<dyn Fn(&mut S, &mut ViewContext<S>) -> AnyElement<S> + Send + Sync + 'static>,
|
||||||
parent_state_type: PhantomData<P>,
|
parent_state_type: PhantomData<P>,
|
||||||
|
@ -21,7 +21,7 @@ impl<S: 'static + Send + Sync, P: 'static + Send> View<S, P> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, P> Clone for View<S, P> {
|
impl<S: Send + Sync, P> Clone for View<S, P> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
state: self.state.clone(),
|
state: self.state.clone(),
|
||||||
|
@ -33,10 +33,15 @@ impl<S, P> Clone for View<S, P> {
|
||||||
|
|
||||||
pub type RootView<S> = View<S, ()>;
|
pub type RootView<S> = View<S, ()>;
|
||||||
|
|
||||||
pub fn view<S: 'static, P: 'static, E: Element<State = S>>(
|
pub fn view<S, P, E>(
|
||||||
state: Handle<S>,
|
state: Handle<S>,
|
||||||
render: impl Fn(&mut S, &mut ViewContext<S>) -> E + Send + Sync + 'static,
|
render: impl Fn(&mut S, &mut ViewContext<S>) -> E + Send + Sync + 'static,
|
||||||
) -> View<S, P> {
|
) -> View<S, P>
|
||||||
|
where
|
||||||
|
S: 'static + Send + Sync,
|
||||||
|
P: 'static,
|
||||||
|
E: Element<State = S>,
|
||||||
|
{
|
||||||
View {
|
View {
|
||||||
state,
|
state,
|
||||||
render: Arc::new(move |state, cx| render(state, cx).into_any()),
|
render: Arc::new(move |state, cx| render(state, cx).into_any()),
|
||||||
|
|
|
@ -275,10 +275,7 @@ impl<'a, 'w, T: Send + Sync + 'static> ViewContext<'a, 'w, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle(&self) -> WeakHandle<T> {
|
pub fn handle(&self) -> WeakHandle<T> {
|
||||||
WeakHandle {
|
self.entities.weak_handle(self.entity_id)
|
||||||
id: self.entity_id,
|
|
||||||
entity_type: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn observe<E: Send + Sync + 'static>(
|
pub fn observe<E: Send + Sync + 'static>(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue