WIP: Try to store an Rc<RefCell> inside entity handles
This commit is contained in:
parent
df57754baf
commit
6256e80933
10 changed files with 123 additions and 130 deletions
|
@ -402,7 +402,7 @@ impl AppContext for ExampleContext {
|
|||
self.app.new(build_entity)
|
||||
}
|
||||
|
||||
fn reserve_entity<T: 'static>(&mut self) -> Self::Result<gpui::Reservation<T>> {
|
||||
fn reserve_entity(&mut self) -> Self::Result<gpui::Reservation<T>> {
|
||||
self.app.reserve_entity()
|
||||
}
|
||||
|
||||
|
|
|
@ -38,9 +38,9 @@ use crate::{
|
|||
EventEmitter, FocusHandle, FocusMap, ForegroundExecutor, Global, KeyBinding, KeyContext,
|
||||
Keymap, Keystroke, LayoutId, Menu, MenuItem, OwnedMenu, PathPromptOptions, Pixels, Platform,
|
||||
PlatformDisplay, PlatformKeyboardLayout, Point, PromptBuilder, PromptButton, PromptHandle,
|
||||
PromptLevel, Render, RenderImage, RenderablePromptHandle, Reservation, ScreenCaptureSource,
|
||||
SubscriberSet, Subscription, SvgRenderer, Task, TextSystem, Window, WindowAppearance,
|
||||
WindowHandle, WindowId, WindowInvalidator,
|
||||
PromptLevel, Render, RenderImage, RenderablePromptHandle, ScreenCaptureSource, SubscriberSet,
|
||||
Subscription, SvgRenderer, Task, TextSystem, Window, WindowAppearance, WindowHandle, WindowId,
|
||||
WindowInvalidator,
|
||||
colors::{Colors, GlobalColors},
|
||||
current_platform, hash, init_app_menus,
|
||||
};
|
||||
|
@ -930,11 +930,11 @@ impl App {
|
|||
break;
|
||||
}
|
||||
|
||||
for (entity_id, mut entity) in dropped {
|
||||
for (entity_id, entity) in dropped {
|
||||
self.observers.remove(&entity_id);
|
||||
self.event_listeners.remove(&entity_id);
|
||||
for release_callback in self.release_listeners.remove(&entity_id) {
|
||||
release_callback(entity.as_mut(), self);
|
||||
release_callback(entity.borrow_mut().deref_mut(), self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1746,9 +1746,9 @@ impl AppContext for App {
|
|||
/// [`Entity`] handle will be returned, which can be used to access the entity in a context.
|
||||
fn new<T: 'static>(&mut self, build_entity: impl FnOnce(&mut Context<T>) -> T) -> Entity<T> {
|
||||
self.update(|cx| {
|
||||
let slot = cx.entities.reserve();
|
||||
let handle = slot.clone();
|
||||
let entity = build_entity(&mut Context::new_context(cx, slot.downgrade()));
|
||||
let entity_id = cx.entities.reserve();
|
||||
let entity = build_entity(&mut Context::new_context(cx, entity_id, None));
|
||||
let handle = cx.entities.insert(entity_id, entity);
|
||||
|
||||
cx.push_effect(Effect::EntityCreated {
|
||||
entity: handle.clone().into_any(),
|
||||
|
@ -1756,24 +1756,22 @@ impl AppContext for App {
|
|||
window: cx.window_update_stack.last().cloned(),
|
||||
});
|
||||
|
||||
cx.entities.insert(slot, entity);
|
||||
handle
|
||||
})
|
||||
}
|
||||
|
||||
fn reserve_entity<T: 'static>(&mut self) -> Self::Result<Reservation<T>> {
|
||||
Reservation(self.entities.reserve())
|
||||
fn reserve_entity(&mut self) -> Self::Result<EntityId> {
|
||||
self.entities.reserve()
|
||||
}
|
||||
|
||||
fn insert_entity<T: 'static>(
|
||||
&mut self,
|
||||
reservation: Reservation<T>,
|
||||
entity_id: EntityId,
|
||||
build_entity: impl FnOnce(&mut Context<T>) -> T,
|
||||
) -> Self::Result<Entity<T>> {
|
||||
self.update(|cx| {
|
||||
let slot = reservation.0;
|
||||
let entity = build_entity(&mut Context::new_context(cx, slot.downgrade()));
|
||||
cx.entities.insert(slot, entity)
|
||||
let entity = build_entity(&mut Context::new_context(cx, entity_id, None));
|
||||
cx.entities.insert(entity_id, entity)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1785,13 +1783,11 @@ impl AppContext for App {
|
|||
update: impl FnOnce(&mut T, &mut Context<T>) -> R,
|
||||
) -> R {
|
||||
self.update(|cx| {
|
||||
let mut entity = cx.entities.lease(handle);
|
||||
let result = update(
|
||||
&mut entity,
|
||||
&mut Context::new_context(cx, handle.downgrade()),
|
||||
);
|
||||
cx.entities.end_lease(entity);
|
||||
result
|
||||
let mut entity = cx.entities.get(handle.entity_id());
|
||||
update(
|
||||
entity.borrow_mut().downcast_mut().unwrap(),
|
||||
&mut Context::new_context(cx, handle.entity_id(), Some(handle.downgrade())),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use crate::{
|
||||
AnyView, AnyWindowHandle, App, AppCell, AppContext, BackgroundExecutor, BorrowAppContext,
|
||||
Entity, EventEmitter, Focusable, ForegroundExecutor, Global, PromptButton, PromptLevel, Render,
|
||||
Reservation, Result, Subscription, Task, VisualContext, Window, WindowHandle,
|
||||
Entity, EntityId, EventEmitter, Focusable, ForegroundExecutor, Global, PromptButton,
|
||||
PromptLevel, Render, Result, Subscription, Task, VisualContext, Window, WindowHandle,
|
||||
app::NewEntityListener,
|
||||
};
|
||||
use anyhow::Context as _;
|
||||
use derive_more::{Deref, DerefMut};
|
||||
|
@ -32,7 +33,7 @@ impl AppContext for AsyncApp {
|
|||
Ok(app.new(build_entity))
|
||||
}
|
||||
|
||||
fn reserve_entity<T: 'static>(&mut self) -> Result<Reservation<T>> {
|
||||
fn reserve_entity(&mut self) -> Result<EntityId> {
|
||||
let app = self.app.upgrade().context("app was released")?;
|
||||
let mut app = app.borrow_mut();
|
||||
Ok(app.reserve_entity())
|
||||
|
@ -40,12 +41,12 @@ impl AppContext for AsyncApp {
|
|||
|
||||
fn insert_entity<T: 'static>(
|
||||
&mut self,
|
||||
reservation: Reservation<T>,
|
||||
entity_id: EntityId,
|
||||
build_entity: impl FnOnce(&mut Context<T>) -> T,
|
||||
) -> Result<Entity<T>> {
|
||||
let app = self.app.upgrade().context("app was released")?;
|
||||
let mut app = app.borrow_mut();
|
||||
Ok(app.insert_entity(reservation, build_entity))
|
||||
Ok(app.insert_entity(entity_id, build_entity))
|
||||
}
|
||||
|
||||
fn update_entity<T: 'static, R>(
|
||||
|
@ -342,17 +343,17 @@ impl AppContext for AsyncWindowContext {
|
|||
self.window.update(self, |_, _, cx| cx.new(build_entity))
|
||||
}
|
||||
|
||||
fn reserve_entity<T: 'static>(&mut self) -> Result<Reservation<T>> {
|
||||
fn reserve_entity(&mut self) -> Result<EntityId> {
|
||||
self.window.update(self, |_, _, cx| cx.reserve_entity())
|
||||
}
|
||||
|
||||
fn insert_entity<T: 'static>(
|
||||
&mut self,
|
||||
reservation: Reservation<T>,
|
||||
entity_id: EntityId,
|
||||
build_entity: impl FnOnce(&mut Context<T>) -> T,
|
||||
) -> Self::Result<Entity<T>> {
|
||||
self.window
|
||||
.update(self, |_, _, cx| cx.insert_entity(reservation, build_entity))
|
||||
.update(self, |_, _, cx| cx.insert_entity(entity_id, build_entity))
|
||||
}
|
||||
|
||||
fn update_entity<T: 'static, R>(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
AnyView, AnyWindowHandle, AppContext, AsyncApp, DispatchPhase, Effect, EntityId, EventEmitter,
|
||||
FocusHandle, FocusOutEvent, Focusable, Global, KeystrokeObserver, Reservation, SubscriberSet,
|
||||
Subscription, Task, WeakEntity, WeakFocusHandle, Window, WindowHandle,
|
||||
FocusHandle, FocusOutEvent, Focusable, Global, KeystrokeObserver, SubscriberSet, Subscription,
|
||||
Task, WeakEntity, WeakFocusHandle, Window, WindowHandle,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use derive_more::{Deref, DerefMut};
|
||||
|
@ -22,17 +22,26 @@ pub struct Context<'a, T> {
|
|||
#[deref]
|
||||
#[deref_mut]
|
||||
app: &'a mut App,
|
||||
entity_state: WeakEntity<T>,
|
||||
entity_id: EntityId,
|
||||
entity_state: Option<WeakEntity<T>>,
|
||||
}
|
||||
|
||||
impl<'a, T: 'static> Context<'a, T> {
|
||||
pub(crate) fn new_context(app: &'a mut App, entity_state: WeakEntity<T>) -> Self {
|
||||
Self { app, entity_state }
|
||||
pub(crate) fn new_context(
|
||||
app: &'a mut App,
|
||||
entity_id: EntityId,
|
||||
entity_state: Option<WeakEntity<T>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
app,
|
||||
entity_id,
|
||||
entity_state,
|
||||
}
|
||||
}
|
||||
|
||||
/// The entity id of the entity backing this context.
|
||||
pub fn entity_id(&self) -> EntityId {
|
||||
self.entity_state.entity_id
|
||||
self.entity_id
|
||||
}
|
||||
|
||||
/// Returns a handle to the entity belonging to this context.
|
||||
|
@ -44,7 +53,7 @@ impl<'a, T: 'static> Context<'a, T> {
|
|||
|
||||
/// Returns a weak handle to the entity belonging to this context.
|
||||
pub fn weak_entity(&self) -> WeakEntity<T> {
|
||||
self.entity_state.clone()
|
||||
self.entity_state.as_ref().unwrap().clone()
|
||||
}
|
||||
|
||||
/// Arranges for the given function to be called whenever [`Context::notify`] is
|
||||
|
@ -112,7 +121,7 @@ impl<'a, T: 'static> Context<'a, T> {
|
|||
T: 'static,
|
||||
{
|
||||
let (subscription, activate) = self.app.release_listeners.insert(
|
||||
self.entity_state.entity_id,
|
||||
self.entity_id,
|
||||
Box::new(move |this, cx| {
|
||||
let this = this.downcast_mut().expect("invalid entity type");
|
||||
on_release(this, cx);
|
||||
|
@ -193,7 +202,7 @@ impl<'a, T: 'static> Context<'a, T> {
|
|||
|
||||
/// Tell GPUI that this entity has changed and observers of it should be notified.
|
||||
pub fn notify(&mut self) {
|
||||
self.app.notify(self.entity_state.entity_id);
|
||||
self.app.notify(self.entity_id);
|
||||
}
|
||||
|
||||
/// Spawn the future returned by the given function.
|
||||
|
@ -692,7 +701,7 @@ impl<T> Context<'_, T> {
|
|||
Evt: 'static,
|
||||
{
|
||||
self.app.pending_effects.push_back(Effect::Emit {
|
||||
emitter: self.entity_state.entity_id,
|
||||
emitter: self.entity_id,
|
||||
event_type: TypeId::of::<Evt>(),
|
||||
event: Box::new(event),
|
||||
});
|
||||
|
@ -706,16 +715,16 @@ impl<T> AppContext for Context<'_, T> {
|
|||
self.app.new(build_entity)
|
||||
}
|
||||
|
||||
fn reserve_entity<U: 'static>(&mut self) -> Reservation<U> {
|
||||
fn reserve_entity(&mut self) -> EntityId {
|
||||
self.app.reserve_entity()
|
||||
}
|
||||
|
||||
fn insert_entity<U: 'static>(
|
||||
&mut self,
|
||||
reservation: Reservation<U>,
|
||||
entity_id: EntityId,
|
||||
build_entity: impl FnOnce(&mut Context<U>) -> U,
|
||||
) -> Self::Result<Entity<U>> {
|
||||
self.app.insert_entity(reservation, build_entity)
|
||||
self.app.insert_entity(entity_id, build_entity)
|
||||
}
|
||||
|
||||
fn update_entity<U: 'static, R>(
|
||||
|
|
|
@ -13,6 +13,7 @@ use std::{
|
|||
marker::PhantomData,
|
||||
mem,
|
||||
num::NonZeroU64,
|
||||
rc::{self, Rc},
|
||||
sync::{
|
||||
Arc, Weak,
|
||||
atomic::{AtomicU64, AtomicUsize, Ordering::SeqCst},
|
||||
|
@ -55,9 +56,9 @@ impl Display for EntityId {
|
|||
}
|
||||
|
||||
pub(crate) struct EntityMap {
|
||||
entities: SecondaryMap<EntityId, Box<dyn Any>>,
|
||||
entities: SecondaryMap<EntityId, Rc<RefCell<dyn Any>>>,
|
||||
pub accessed_entities: RefCell<FxHashSet<EntityId>>,
|
||||
ref_counts: Arc<RwLock<EntityRefCounts>>,
|
||||
pub(crate) ref_counts: Arc<RwLock<EntityRefCounts>>,
|
||||
}
|
||||
|
||||
struct EntityRefCounts {
|
||||
|
@ -85,47 +86,28 @@ impl EntityMap {
|
|||
}
|
||||
|
||||
/// Reserve a slot for an entity, which you can subsequently use with `insert`.
|
||||
pub fn reserve<T: 'static>(&self) -> Slot<T> {
|
||||
let id = self.ref_counts.write().counts.insert(1.into());
|
||||
Slot(Entity::new(id, Arc::downgrade(&self.ref_counts)))
|
||||
pub fn reserve(&self) -> EntityId {
|
||||
self.ref_counts.write().counts.insert(1.into())
|
||||
}
|
||||
|
||||
/// Insert an entity into a slot obtained by calling `reserve`.
|
||||
pub fn insert<T>(&mut self, slot: Slot<T>, entity: T) -> Entity<T>
|
||||
pub fn insert<T>(&mut self, entity_id: EntityId, entity: T) -> Entity<T>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
let mut accessed_entities = self.accessed_entities.borrow_mut();
|
||||
accessed_entities.insert(slot.entity_id);
|
||||
accessed_entities.insert(entity_id);
|
||||
|
||||
let handle = slot.0;
|
||||
self.entities.insert(handle.entity_id, Box::new(entity));
|
||||
handle
|
||||
let entity_data = Rc::new(RefCell::new(entity));
|
||||
self.entities.insert(entity_id, entity_data.clone());
|
||||
|
||||
Entity::new(entity_id, entity_data, Arc::downgrade(&self.ref_counts))
|
||||
}
|
||||
|
||||
/// Move an entity to the stack.
|
||||
#[track_caller]
|
||||
pub fn lease<'a, T>(&mut self, pointer: &'a Entity<T>) -> Lease<'a, T> {
|
||||
self.assert_valid_context(pointer);
|
||||
pub fn get(&self, entity_id: EntityId) -> Rc<RefCell<dyn Any>> {
|
||||
let mut accessed_entities = self.accessed_entities.borrow_mut();
|
||||
accessed_entities.insert(pointer.entity_id);
|
||||
|
||||
let entity = Some(
|
||||
self.entities
|
||||
.remove(pointer.entity_id)
|
||||
.unwrap_or_else(|| double_lease_panic::<T>("update")),
|
||||
);
|
||||
Lease {
|
||||
entity,
|
||||
pointer,
|
||||
entity_type: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an entity after moving it to the stack.
|
||||
pub fn end_lease<T>(&mut self, mut lease: Lease<T>) {
|
||||
self.entities
|
||||
.insert(lease.pointer.entity_id, lease.entity.take().unwrap());
|
||||
accessed_entities.insert(entity_id);
|
||||
self.entities.get(entity_id).unwrap().clone()
|
||||
}
|
||||
|
||||
pub fn read<T: 'static>(&self, entity: &Entity<T>) -> &T {
|
||||
|
@ -133,15 +115,16 @@ impl EntityMap {
|
|||
let mut accessed_entities = self.accessed_entities.borrow_mut();
|
||||
accessed_entities.insert(entity.entity_id);
|
||||
|
||||
self.entities
|
||||
.get(entity.entity_id)
|
||||
.and_then(|entity| entity.downcast_ref())
|
||||
.unwrap_or_else(|| double_lease_panic::<T>("read"))
|
||||
// self.entities
|
||||
// .get(entity.entity_id)
|
||||
// .and_then(|entity| entity.borrow().downcast_ref())
|
||||
// .unwrap_or_else(|| double_lease_panic::<T>("read"))
|
||||
todo!("interface will need to change here")
|
||||
}
|
||||
|
||||
fn assert_valid_context(&self, entity: &AnyEntity) {
|
||||
debug_assert!(
|
||||
Weak::ptr_eq(&entity.entity_map, &Arc::downgrade(&self.ref_counts)),
|
||||
Weak::ptr_eq(&entity.ref_counts, &Arc::downgrade(&self.ref_counts)),
|
||||
"used a entity with the wrong context"
|
||||
);
|
||||
}
|
||||
|
@ -156,7 +139,7 @@ impl EntityMap {
|
|||
self.accessed_entities.borrow_mut().clear();
|
||||
}
|
||||
|
||||
pub fn take_dropped(&mut self) -> Vec<(EntityId, Box<dyn Any>)> {
|
||||
pub fn take_dropped(&mut self) -> Vec<(EntityId, Rc<RefCell<dyn Any>>)> {
|
||||
let mut ref_counts = self.ref_counts.write();
|
||||
let dropped_entity_ids = mem::take(&mut ref_counts.dropped_entity_ids);
|
||||
let mut accessed_entities = self.accessed_entities.borrow_mut();
|
||||
|
@ -222,19 +205,26 @@ pub(crate) struct Slot<T>(Entity<T>);
|
|||
pub struct AnyEntity {
|
||||
pub(crate) entity_id: EntityId,
|
||||
pub(crate) entity_type: TypeId,
|
||||
entity_map: Weak<RwLock<EntityRefCounts>>,
|
||||
entity_data: Rc<RefCell<dyn Any>>,
|
||||
ref_counts: Weak<RwLock<EntityRefCounts>>,
|
||||
#[cfg(any(test, feature = "leak-detection"))]
|
||||
handle_id: HandleId,
|
||||
}
|
||||
|
||||
impl AnyEntity {
|
||||
fn new(id: EntityId, entity_type: TypeId, entity_map: Weak<RwLock<EntityRefCounts>>) -> Self {
|
||||
fn new(
|
||||
id: EntityId,
|
||||
entity_type: TypeId,
|
||||
entity_data: Rc<RefCell<dyn Any>>,
|
||||
ref_counts: Weak<RwLock<EntityRefCounts>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
entity_id: id,
|
||||
entity_type,
|
||||
entity_map: entity_map.clone(),
|
||||
entity_data,
|
||||
ref_counts: ref_counts.clone(),
|
||||
#[cfg(any(test, feature = "leak-detection"))]
|
||||
handle_id: entity_map
|
||||
handle_id: ref_counts
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.write()
|
||||
|
@ -258,7 +248,8 @@ impl AnyEntity {
|
|||
AnyWeakEntity {
|
||||
entity_id: self.entity_id,
|
||||
entity_type: self.entity_type,
|
||||
entity_ref_counts: self.entity_map.clone(),
|
||||
entity_data: Rc::downgrade(&self.entity_data),
|
||||
entity_ref_counts: self.ref_counts.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,7 +269,7 @@ impl AnyEntity {
|
|||
|
||||
impl Clone for AnyEntity {
|
||||
fn clone(&self) -> Self {
|
||||
if let Some(entity_map) = self.entity_map.upgrade() {
|
||||
if let Some(entity_map) = self.ref_counts.upgrade() {
|
||||
let entity_map = entity_map.read();
|
||||
let count = entity_map
|
||||
.counts
|
||||
|
@ -291,10 +282,11 @@ impl Clone for AnyEntity {
|
|||
Self {
|
||||
entity_id: self.entity_id,
|
||||
entity_type: self.entity_type,
|
||||
entity_map: self.entity_map.clone(),
|
||||
entity_data: self.entity_data.clone(),
|
||||
ref_counts: self.ref_counts.clone(),
|
||||
#[cfg(any(test, feature = "leak-detection"))]
|
||||
handle_id: self
|
||||
.entity_map
|
||||
.ref_counts
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.write()
|
||||
|
@ -306,7 +298,7 @@ impl Clone for AnyEntity {
|
|||
|
||||
impl Drop for AnyEntity {
|
||||
fn drop(&mut self) {
|
||||
if let Some(entity_map) = self.entity_map.upgrade() {
|
||||
if let Some(entity_map) = self.ref_counts.upgrade() {
|
||||
let entity_map = entity_map.upgradable_read();
|
||||
let count = entity_map
|
||||
.counts
|
||||
|
@ -322,7 +314,7 @@ impl Drop for AnyEntity {
|
|||
}
|
||||
|
||||
#[cfg(any(test, feature = "leak-detection"))]
|
||||
if let Some(entity_map) = self.entity_map.upgrade() {
|
||||
if let Some(entity_map) = self.ref_counts.upgrade() {
|
||||
entity_map
|
||||
.write()
|
||||
.leak_detector
|
||||
|
@ -386,12 +378,16 @@ unsafe impl<T> Sync for Entity<T> {}
|
|||
impl<T> Sealed for Entity<T> {}
|
||||
|
||||
impl<T: 'static> Entity<T> {
|
||||
fn new(id: EntityId, entity_map: Weak<RwLock<EntityRefCounts>>) -> Self
|
||||
fn new(
|
||||
id: EntityId,
|
||||
entity_data: Rc<RefCell<T>>,
|
||||
ref_counts: Weak<RwLock<EntityRefCounts>>,
|
||||
) -> Self
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
Self {
|
||||
any_entity: AnyEntity::new(id, TypeId::of::<T>(), entity_map),
|
||||
any_entity: AnyEntity::new(id, TypeId::of::<T>(), entity_data, ref_counts),
|
||||
entity_type: PhantomData,
|
||||
}
|
||||
}
|
||||
|
@ -504,6 +500,7 @@ impl<T: 'static> PartialOrd for Entity<T> {
|
|||
pub struct AnyWeakEntity {
|
||||
pub(crate) entity_id: EntityId,
|
||||
entity_type: TypeId,
|
||||
entity_data: rc::Weak<RefCell<dyn Any>>,
|
||||
entity_ref_counts: Weak<RwLock<EntityRefCounts>>,
|
||||
}
|
||||
|
||||
|
@ -538,7 +535,8 @@ impl AnyWeakEntity {
|
|||
Some(AnyEntity {
|
||||
entity_id: self.entity_id,
|
||||
entity_type: self.entity_type,
|
||||
entity_map: self.entity_ref_counts.clone(),
|
||||
entity_data: self.entity_data.upgrade()?,
|
||||
ref_counts: self.entity_ref_counts.clone(),
|
||||
#[cfg(any(test, feature = "leak-detection"))]
|
||||
handle_id: self
|
||||
.entity_ref_counts
|
||||
|
@ -592,6 +590,7 @@ impl AnyWeakEntity {
|
|||
// read in the first place, so we're good!
|
||||
entity_id: entity_id.into(),
|
||||
entity_type: TypeId::of::<()>(),
|
||||
entity_data: Rc::downgrade(&(Rc::new(RefCell::new(())) as Rc<RefCell<dyn Any>>)),
|
||||
entity_ref_counts: Weak::new(),
|
||||
}
|
||||
}
|
||||
|
@ -836,10 +835,10 @@ mod test {
|
|||
// Tests that slots are not re-used before take_dropped.
|
||||
let mut entity_map = EntityMap::new();
|
||||
|
||||
let slot = entity_map.reserve::<TestEntity>();
|
||||
let slot = entity_map.reserve();
|
||||
entity_map.insert(slot, TestEntity { i: 1 });
|
||||
|
||||
let slot = entity_map.reserve::<TestEntity>();
|
||||
let slot = entity_map.reserve();
|
||||
entity_map.insert(slot, TestEntity { i: 2 });
|
||||
|
||||
let dropped = entity_map.take_dropped();
|
||||
|
@ -848,7 +847,7 @@ mod test {
|
|||
assert_eq!(
|
||||
dropped
|
||||
.into_iter()
|
||||
.map(|(_, entity)| entity.downcast::<TestEntity>().unwrap().i)
|
||||
.map(|(_, entity)| entity.borrow().downcast_ref::<TestEntity>().unwrap().i)
|
||||
.collect::<Vec<i32>>(),
|
||||
vec![1, 2],
|
||||
);
|
||||
|
@ -859,7 +858,7 @@ mod test {
|
|||
// Tests that weak handles are not upgraded before take_dropped
|
||||
let mut entity_map = EntityMap::new();
|
||||
|
||||
let slot = entity_map.reserve::<TestEntity>();
|
||||
let slot = entity_map.reserve();
|
||||
let handle = entity_map.insert(slot, TestEntity { i: 1 });
|
||||
let weak = handle.downgrade();
|
||||
drop(handle);
|
||||
|
@ -873,7 +872,7 @@ mod test {
|
|||
assert_eq!(
|
||||
dropped
|
||||
.into_iter()
|
||||
.map(|(_, entity)| entity.downcast::<TestEntity>().unwrap().i)
|
||||
.map(|(_, entity)| entity.borrow().downcast_ref::<TestEntity>().unwrap().i)
|
||||
.collect::<Vec<i32>>(),
|
||||
vec![1],
|
||||
);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use crate::{
|
||||
Action, AnyView, AnyWindowHandle, App, AppCell, AppContext, AsyncApp, AvailableSpace,
|
||||
BackgroundExecutor, BorrowAppContext, Bounds, Capslock, ClipboardItem, DrawPhase, Drawable,
|
||||
Element, Empty, EventEmitter, ForegroundExecutor, Global, InputEvent, Keystroke, Modifiers,
|
||||
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels,
|
||||
Platform, Point, Render, Result, Size, Task, TestDispatcher, TestPlatform,
|
||||
Element, Empty, EntityId, EventEmitter, ForegroundExecutor, Global, InputEvent, Keystroke,
|
||||
Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
|
||||
Pixels, Platform, Point, Render, Result, Size, Task, TestDispatcher, TestPlatform,
|
||||
TestScreenCaptureSource, TestWindow, TextSystem, VisualContext, Window, WindowBounds,
|
||||
WindowHandle, WindowOptions,
|
||||
};
|
||||
|
@ -40,14 +40,14 @@ impl AppContext for TestAppContext {
|
|||
app.new(build_entity)
|
||||
}
|
||||
|
||||
fn reserve_entity<T: 'static>(&mut self) -> Self::Result<crate::Reservation<T>> {
|
||||
fn reserve_entity(&mut self) -> Self::Result<EntityId> {
|
||||
let mut app = self.app.borrow_mut();
|
||||
app.reserve_entity()
|
||||
}
|
||||
|
||||
fn insert_entity<T: 'static>(
|
||||
&mut self,
|
||||
reservation: crate::Reservation<T>,
|
||||
reservation: EntityId,
|
||||
build_entity: impl FnOnce(&mut Context<T>) -> T,
|
||||
) -> Self::Result<Entity<T>> {
|
||||
let mut app = self.app.borrow_mut();
|
||||
|
@ -891,13 +891,13 @@ impl AppContext for VisualTestContext {
|
|||
self.cx.new(build_entity)
|
||||
}
|
||||
|
||||
fn reserve_entity<T: 'static>(&mut self) -> Self::Result<crate::Reservation<T>> {
|
||||
fn reserve_entity(&mut self) -> Self::Result<EntityId> {
|
||||
self.cx.reserve_entity()
|
||||
}
|
||||
|
||||
fn insert_entity<T: 'static>(
|
||||
&mut self,
|
||||
reservation: crate::Reservation<T>,
|
||||
reservation: EntityId,
|
||||
build_entity: impl FnOnce(&mut Context<T>) -> T,
|
||||
) -> Self::Result<Entity<T>> {
|
||||
self.cx.insert_entity(reservation, build_entity)
|
||||
|
|
|
@ -175,16 +175,15 @@ pub trait AppContext {
|
|||
build_entity: impl FnOnce(&mut Context<T>) -> T,
|
||||
) -> Self::Result<Entity<T>>;
|
||||
|
||||
/// Reserve a slot for a entity to be inserted later.
|
||||
/// The returned [Reservation] allows you to obtain the [EntityId] for the future entity.
|
||||
fn reserve_entity<T: 'static>(&mut self) -> Self::Result<Reservation<T>>;
|
||||
/// Reserve an EntityId for a entity to be inserted later.
|
||||
fn reserve_entity(&mut self) -> Self::Result<EntityId>;
|
||||
|
||||
/// Insert a new entity in the app context based on a [Reservation] previously obtained from [`reserve_entity`].
|
||||
/// Insert a new entity in the app context based on a [EntityId] previously obtained from [`reserve_entity`].
|
||||
///
|
||||
/// [`reserve_entity`]: Self::reserve_entity
|
||||
fn insert_entity<T: 'static>(
|
||||
&mut self,
|
||||
reservation: Reservation<T>,
|
||||
reservation: EntityId,
|
||||
build_entity: impl FnOnce(&mut Context<T>) -> T,
|
||||
) -> Self::Result<Entity<T>>;
|
||||
|
||||
|
@ -231,17 +230,6 @@ pub trait AppContext {
|
|||
G: Global;
|
||||
}
|
||||
|
||||
/// Returned by [Context::reserve_entity] to later be passed to [Context::insert_entity].
|
||||
/// Allows you to obtain the [EntityId] for a entity before it is created.
|
||||
pub struct Reservation<T>(pub(crate) Slot<T>);
|
||||
|
||||
impl<T: 'static> Reservation<T> {
|
||||
/// Returns the [EntityId] that will be associated with the entity once it is inserted.
|
||||
pub fn entity_id(&self) -> EntityId {
|
||||
self.0.entity_id()
|
||||
}
|
||||
}
|
||||
|
||||
/// This trait is used for the different visual contexts in GPUI that
|
||||
/// require a window to be present.
|
||||
pub trait VisualContext: AppContext {
|
||||
|
|
|
@ -30,16 +30,16 @@ pub fn derive_app_context(input: TokenStream) -> TokenStream {
|
|||
self.#app_variable.new(build_entity)
|
||||
}
|
||||
|
||||
fn reserve_entity<T: 'static>(&mut self) -> Self::Result<gpui::Reservation<T>> {
|
||||
fn reserve_entity(&mut self) -> Self::Result<EntityId> {
|
||||
self.#app_variable.reserve_entity()
|
||||
}
|
||||
|
||||
fn insert_entity<T: 'static>(
|
||||
&mut self,
|
||||
reservation: gpui::Reservation<T>,
|
||||
entity_id: EntityId,
|
||||
build_entity: impl FnOnce(&mut gpui::Context<'_, T>) -> T,
|
||||
) -> Self::Result<gpui::Entity<T>> {
|
||||
self.#app_variable.insert_entity(reservation, build_entity)
|
||||
self.#app_variable.insert_entity(entity_id, build_entity)
|
||||
}
|
||||
|
||||
fn update_entity<T, R>(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#[test]
|
||||
fn test_derive_context() {
|
||||
use gpui::{App, Window};
|
||||
use gpui::{App, EntityId, Window};
|
||||
use gpui_macros::{AppContext, VisualContext};
|
||||
|
||||
#[derive(AppContext, VisualContext)]
|
||||
|
|
|
@ -967,7 +967,7 @@ impl Buffer {
|
|||
language_registry: Option<Arc<LanguageRegistry>>,
|
||||
cx: &mut App,
|
||||
) -> impl Future<Output = BufferSnapshot> + use<> {
|
||||
let entity_id = cx.reserve_entity::<Self>().entity_id();
|
||||
let entity_id = cx.reserve_entity();
|
||||
let buffer_id = entity_id.as_non_zero_u64().into();
|
||||
async move {
|
||||
let text =
|
||||
|
@ -992,7 +992,7 @@ impl Buffer {
|
|||
}
|
||||
|
||||
pub fn build_empty_snapshot(cx: &mut App) -> BufferSnapshot {
|
||||
let entity_id = cx.reserve_entity::<Self>().entity_id();
|
||||
let entity_id = cx.reserve_entity();
|
||||
let buffer_id = entity_id.as_non_zero_u64().into();
|
||||
let text =
|
||||
TextBuffer::new_normalized(0, buffer_id, Default::default(), Rope::new()).snapshot();
|
||||
|
@ -1015,7 +1015,7 @@ impl Buffer {
|
|||
language_registry: Option<Arc<LanguageRegistry>>,
|
||||
cx: &mut App,
|
||||
) -> BufferSnapshot {
|
||||
let entity_id = cx.reserve_entity::<Self>().entity_id();
|
||||
let entity_id = cx.reserve_entity();
|
||||
let buffer_id = entity_id.as_non_zero_u64().into();
|
||||
let text = TextBuffer::new_normalized(0, buffer_id, Default::default(), text).snapshot();
|
||||
let mut syntax = SyntaxMap::new(&text).snapshot();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue