v1
This commit is contained in:
@@ -362,7 +362,7 @@ impl AppContext {
|
||||
self.observers.remove(&entity_id);
|
||||
self.event_listeners.remove(&entity_id);
|
||||
for mut release_callback in self.release_listeners.remove(&entity_id) {
|
||||
release_callback(&mut entity, self);
|
||||
release_callback(entity.as_mut(), self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ impl Drop for AnyHandle {
|
||||
let count = entity_map
|
||||
.counts
|
||||
.get(self.entity_id)
|
||||
.expect("Detected over-release of a handle.");
|
||||
.expect("detected over-release of a handle.");
|
||||
let prev_count = count.fetch_sub(1, SeqCst);
|
||||
assert_ne!(prev_count, 0, "Detected over-release of a handle.");
|
||||
if prev_count == 1 {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::{
|
||||
AnyWindowHandle, AppContext, AsyncAppContext, Context, Executor, Handle, MainThread,
|
||||
ModelContext, Result, Task, TestDispatcher, TestPlatform, WindowContext,
|
||||
AnyWindowHandle, AppContext, AsyncAppContext, Context, EventEmitter, Executor, Handle,
|
||||
MainThread, ModelContext, Result, Task, TestDispatcher, TestPlatform, WindowContext,
|
||||
};
|
||||
use futures::SinkExt;
|
||||
use parking_lot::Mutex;
|
||||
use std::{any::Any, future::Future, sync::Arc};
|
||||
|
||||
@@ -149,4 +150,39 @@ impl TestAppContext {
|
||||
executor: self.executor.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn subscribe<T: 'static + EventEmitter + Send + Sync>(
|
||||
&mut self,
|
||||
entity: &Handle<T>,
|
||||
) -> futures::channel::mpsc::UnboundedReceiver<T::Event>
|
||||
where
|
||||
T::Event: 'static + Send + Clone,
|
||||
{
|
||||
let (mut tx, rx) = futures::channel::mpsc::unbounded();
|
||||
entity
|
||||
.update(self, |_, cx: &mut ModelContext<T>| {
|
||||
cx.subscribe(&entity, move |_, _, event, _| {
|
||||
let _ = tx.send(event.clone());
|
||||
})
|
||||
})
|
||||
.detach();
|
||||
rx
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn subscribe<T: Entity>(
|
||||
// entity: &impl Handle<T>,
|
||||
// cx: &mut TestAppContext,
|
||||
// ) -> Observation<T::Event>
|
||||
// where
|
||||
// T::Event: Clone,
|
||||
// {
|
||||
// let (tx, rx) = smol::channel::unbounded();
|
||||
// let _subscription = cx.update(|cx| {
|
||||
// cx.subscribe(entity, move |_, event, _| {
|
||||
// let _ = smol::block_on(tx.send(event.clone()));
|
||||
// })
|
||||
// });
|
||||
|
||||
// Observation { rx, _subscription }
|
||||
// }
|
||||
|
||||
@@ -147,8 +147,10 @@ impl Executor {
|
||||
Poll::Pending => {
|
||||
if !self.dispatcher.poll() {
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
if let Some(_) = self.dispatcher.as_test() {
|
||||
panic!("blocked with nothing left to run")
|
||||
if let Some(test) = self.dispatcher.as_test() {
|
||||
if !test.parking_allowed() {
|
||||
panic!("blocked with nothing left to run")
|
||||
}
|
||||
}
|
||||
parker.park();
|
||||
}
|
||||
@@ -216,7 +218,7 @@ impl Executor {
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn simulate_random_delay(&self) -> impl Future<Output = ()> {
|
||||
self.dispatcher.as_test().unwrap().simulate_random_delay()
|
||||
self.spawn(self.dispatcher.as_test().unwrap().simulate_random_delay())
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
@@ -229,6 +231,11 @@ impl Executor {
|
||||
self.dispatcher.as_test().unwrap().run_until_parked()
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn allow_parking(&self) {
|
||||
self.dispatcher.as_test().unwrap().allow_parking();
|
||||
}
|
||||
|
||||
pub fn num_cpus(&self) -> usize {
|
||||
num_cpus::get()
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ struct TestDispatcherState {
|
||||
time: Duration,
|
||||
is_main_thread: bool,
|
||||
next_id: TestDispatcherId,
|
||||
allow_parking: bool,
|
||||
}
|
||||
|
||||
impl TestDispatcher {
|
||||
@@ -40,6 +41,7 @@ impl TestDispatcher {
|
||||
time: Duration::ZERO,
|
||||
is_main_thread: true,
|
||||
next_id: TestDispatcherId(1),
|
||||
allow_parking: false,
|
||||
};
|
||||
|
||||
TestDispatcher {
|
||||
@@ -66,7 +68,7 @@ impl TestDispatcher {
|
||||
self.state.lock().time = new_now;
|
||||
}
|
||||
|
||||
pub fn simulate_random_delay(&self) -> impl Future<Output = ()> {
|
||||
pub fn simulate_random_delay(&self) -> impl 'static + Send + Future<Output = ()> {
|
||||
pub struct YieldNow {
|
||||
count: usize,
|
||||
}
|
||||
@@ -75,6 +77,7 @@ impl TestDispatcher {
|
||||
type Output = ();
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
eprintln!("self.count: {}", self.count);
|
||||
if self.count > 0 {
|
||||
self.count -= 1;
|
||||
cx.waker().wake_by_ref();
|
||||
@@ -93,6 +96,14 @@ impl TestDispatcher {
|
||||
pub fn run_until_parked(&self) {
|
||||
while self.poll() {}
|
||||
}
|
||||
|
||||
pub fn parking_allowed(&self) -> bool {
|
||||
self.state.lock().allow_parking
|
||||
}
|
||||
|
||||
pub fn allow_parking(&self) {
|
||||
self.state.lock().allow_parking = true
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for TestDispatcher {
|
||||
|
||||
Reference in New Issue
Block a user