Merge pull request #194 from zed-industries/investigate-compile-time
Explore some ways to reduce Zed's compile time
This commit is contained in:
+104
-64
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
elements::ElementBox,
|
||||
executor,
|
||||
executor::{self, Task},
|
||||
keymap::{self, Keystroke},
|
||||
platform::{self, CursorStyle, Platform, PromptLevel, WindowOptions},
|
||||
presenter::Presenter,
|
||||
@@ -8,7 +8,6 @@ use crate::{
|
||||
AssetCache, AssetSource, ClipboardItem, FontCache, PathPromptOptions, TextLayoutCache,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use async_task::Task;
|
||||
use keymap::MatchResult;
|
||||
use parking_lot::Mutex;
|
||||
use platform::Event;
|
||||
@@ -58,18 +57,19 @@ pub trait ReadModel {
|
||||
}
|
||||
|
||||
pub trait ReadModelWith {
|
||||
fn read_model_with<E: Entity, F: FnOnce(&E, &AppContext) -> T, T>(
|
||||
fn read_model_with<E: Entity, T>(
|
||||
&self,
|
||||
handle: &ModelHandle<E>,
|
||||
read: F,
|
||||
read: &mut dyn FnMut(&E, &AppContext) -> T,
|
||||
) -> T;
|
||||
}
|
||||
|
||||
pub trait UpdateModel {
|
||||
fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
|
||||
where
|
||||
T: Entity,
|
||||
F: FnOnce(&mut T, &mut ModelContext<T>) -> S;
|
||||
fn update_model<T: Entity, O>(
|
||||
&mut self,
|
||||
handle: &ModelHandle<T>,
|
||||
update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
|
||||
) -> O;
|
||||
}
|
||||
|
||||
pub trait UpgradeModelHandle {
|
||||
@@ -82,17 +82,23 @@ pub trait ReadView {
|
||||
}
|
||||
|
||||
pub trait ReadViewWith {
|
||||
fn read_view_with<V, F, T>(&self, handle: &ViewHandle<V>, read: F) -> T
|
||||
fn read_view_with<V, T>(
|
||||
&self,
|
||||
handle: &ViewHandle<V>,
|
||||
read: &mut dyn FnMut(&V, &AppContext) -> T,
|
||||
) -> T
|
||||
where
|
||||
V: View,
|
||||
F: FnOnce(&V, &AppContext) -> T;
|
||||
V: View;
|
||||
}
|
||||
|
||||
pub trait UpdateView {
|
||||
fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
|
||||
fn update_view<T, S>(
|
||||
&mut self,
|
||||
handle: &ViewHandle<T>,
|
||||
update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
|
||||
) -> S
|
||||
where
|
||||
T: View,
|
||||
F: FnOnce(&mut T, &mut ViewContext<T>) -> S;
|
||||
T: View;
|
||||
}
|
||||
|
||||
pub trait Action: 'static + AnyAction {
|
||||
@@ -532,11 +538,11 @@ impl AsyncAppContext {
|
||||
}
|
||||
|
||||
impl UpdateModel for AsyncAppContext {
|
||||
fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
|
||||
where
|
||||
T: Entity,
|
||||
F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
|
||||
{
|
||||
fn update_model<E: Entity, O>(
|
||||
&mut self,
|
||||
handle: &ModelHandle<E>,
|
||||
update: &mut dyn FnMut(&mut E, &mut ModelContext<E>) -> O,
|
||||
) -> O {
|
||||
let mut state = self.0.borrow_mut();
|
||||
state.pending_flushes += 1;
|
||||
let result = state.update_model(handle, update);
|
||||
@@ -555,10 +561,10 @@ impl UpgradeModelHandle for AsyncAppContext {
|
||||
}
|
||||
|
||||
impl ReadModelWith for AsyncAppContext {
|
||||
fn read_model_with<E: Entity, F: FnOnce(&E, &AppContext) -> T, T>(
|
||||
fn read_model_with<E: Entity, T>(
|
||||
&self,
|
||||
handle: &ModelHandle<E>,
|
||||
read: F,
|
||||
read: &mut dyn FnMut(&E, &AppContext) -> T,
|
||||
) -> T {
|
||||
let cx = self.0.borrow();
|
||||
let cx = cx.as_ref();
|
||||
@@ -567,10 +573,13 @@ impl ReadModelWith for AsyncAppContext {
|
||||
}
|
||||
|
||||
impl UpdateView for AsyncAppContext {
|
||||
fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
|
||||
fn update_view<T, S>(
|
||||
&mut self,
|
||||
handle: &ViewHandle<T>,
|
||||
update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
|
||||
) -> S
|
||||
where
|
||||
T: View,
|
||||
F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
|
||||
{
|
||||
let mut state = self.0.borrow_mut();
|
||||
state.pending_flushes += 1;
|
||||
@@ -581,10 +590,13 @@ impl UpdateView for AsyncAppContext {
|
||||
}
|
||||
|
||||
impl ReadViewWith for AsyncAppContext {
|
||||
fn read_view_with<V, F, T>(&self, handle: &ViewHandle<V>, read: F) -> T
|
||||
fn read_view_with<V, T>(
|
||||
&self,
|
||||
handle: &ViewHandle<V>,
|
||||
read: &mut dyn FnMut(&V, &AppContext) -> T,
|
||||
) -> T
|
||||
where
|
||||
V: View,
|
||||
F: FnOnce(&V, &AppContext) -> T,
|
||||
{
|
||||
let cx = self.0.borrow();
|
||||
let cx = cx.as_ref();
|
||||
@@ -593,11 +605,11 @@ impl ReadViewWith for AsyncAppContext {
|
||||
}
|
||||
|
||||
impl UpdateModel for TestAppContext {
|
||||
fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
|
||||
where
|
||||
T: Entity,
|
||||
F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
|
||||
{
|
||||
fn update_model<T: Entity, O>(
|
||||
&mut self,
|
||||
handle: &ModelHandle<T>,
|
||||
update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
|
||||
) -> O {
|
||||
let mut state = self.cx.borrow_mut();
|
||||
state.pending_flushes += 1;
|
||||
let result = state.update_model(handle, update);
|
||||
@@ -607,10 +619,10 @@ impl UpdateModel for TestAppContext {
|
||||
}
|
||||
|
||||
impl ReadModelWith for TestAppContext {
|
||||
fn read_model_with<E: Entity, F: FnOnce(&E, &AppContext) -> T, T>(
|
||||
fn read_model_with<E: Entity, T>(
|
||||
&self,
|
||||
handle: &ModelHandle<E>,
|
||||
read: F,
|
||||
read: &mut dyn FnMut(&E, &AppContext) -> T,
|
||||
) -> T {
|
||||
let cx = self.cx.borrow();
|
||||
let cx = cx.as_ref();
|
||||
@@ -619,10 +631,13 @@ impl ReadModelWith for TestAppContext {
|
||||
}
|
||||
|
||||
impl UpdateView for TestAppContext {
|
||||
fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
|
||||
fn update_view<T, S>(
|
||||
&mut self,
|
||||
handle: &ViewHandle<T>,
|
||||
update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
|
||||
) -> S
|
||||
where
|
||||
T: View,
|
||||
F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
|
||||
{
|
||||
let mut state = self.cx.borrow_mut();
|
||||
state.pending_flushes += 1;
|
||||
@@ -633,10 +648,13 @@ impl UpdateView for TestAppContext {
|
||||
}
|
||||
|
||||
impl ReadViewWith for TestAppContext {
|
||||
fn read_view_with<V, F, T>(&self, handle: &ViewHandle<V>, read: F) -> T
|
||||
fn read_view_with<V, T>(
|
||||
&self,
|
||||
handle: &ViewHandle<V>,
|
||||
read: &mut dyn FnMut(&V, &AppContext) -> T,
|
||||
) -> T
|
||||
where
|
||||
V: View,
|
||||
F: FnOnce(&V, &AppContext) -> T,
|
||||
{
|
||||
let cx = self.cx.borrow();
|
||||
let cx = cx.as_ref();
|
||||
@@ -1630,11 +1648,11 @@ impl ReadModel for MutableAppContext {
|
||||
}
|
||||
|
||||
impl UpdateModel for MutableAppContext {
|
||||
fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
|
||||
where
|
||||
T: Entity,
|
||||
F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
|
||||
{
|
||||
fn update_model<T: Entity, V>(
|
||||
&mut self,
|
||||
handle: &ModelHandle<T>,
|
||||
update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> V,
|
||||
) -> V {
|
||||
if let Some(mut model) = self.cx.models.remove(&handle.model_id) {
|
||||
self.pending_flushes += 1;
|
||||
let mut cx = ModelContext::new(self, handle.model_id);
|
||||
@@ -1674,10 +1692,13 @@ impl ReadView for MutableAppContext {
|
||||
}
|
||||
|
||||
impl UpdateView for MutableAppContext {
|
||||
fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
|
||||
fn update_view<T, S>(
|
||||
&mut self,
|
||||
handle: &ViewHandle<T>,
|
||||
update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
|
||||
) -> S
|
||||
where
|
||||
T: View,
|
||||
F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
|
||||
{
|
||||
self.pending_flushes += 1;
|
||||
let mut view = self
|
||||
@@ -2084,11 +2105,11 @@ impl<M> ReadModel for ModelContext<'_, M> {
|
||||
}
|
||||
|
||||
impl<M> UpdateModel for ModelContext<'_, M> {
|
||||
fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
|
||||
where
|
||||
T: Entity,
|
||||
F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
|
||||
{
|
||||
fn update_model<T: Entity, V>(
|
||||
&mut self,
|
||||
handle: &ModelHandle<T>,
|
||||
update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> V,
|
||||
) -> V {
|
||||
self.app.update_model(handle, update)
|
||||
}
|
||||
}
|
||||
@@ -2345,11 +2366,11 @@ impl<V: View> ReadModel for RenderContext<'_, V> {
|
||||
}
|
||||
|
||||
impl<V: View> UpdateModel for RenderContext<'_, V> {
|
||||
fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
|
||||
where
|
||||
T: Entity,
|
||||
F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
|
||||
{
|
||||
fn update_model<T: Entity, O>(
|
||||
&mut self,
|
||||
handle: &ModelHandle<T>,
|
||||
update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
|
||||
) -> O {
|
||||
self.app.update_model(handle, update)
|
||||
}
|
||||
}
|
||||
@@ -2396,11 +2417,11 @@ impl<V> UpgradeModelHandle for ViewContext<'_, V> {
|
||||
}
|
||||
|
||||
impl<V: View> UpdateModel for ViewContext<'_, V> {
|
||||
fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
|
||||
where
|
||||
T: Entity,
|
||||
F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
|
||||
{
|
||||
fn update_model<T: Entity, O>(
|
||||
&mut self,
|
||||
handle: &ModelHandle<T>,
|
||||
update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
|
||||
) -> O {
|
||||
self.app.update_model(handle, update)
|
||||
}
|
||||
}
|
||||
@@ -2412,10 +2433,13 @@ impl<V: View> ReadView for ViewContext<'_, V> {
|
||||
}
|
||||
|
||||
impl<V: View> UpdateView for ViewContext<'_, V> {
|
||||
fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
|
||||
fn update_view<T, S>(
|
||||
&mut self,
|
||||
handle: &ViewHandle<T>,
|
||||
update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
|
||||
) -> S
|
||||
where
|
||||
T: View,
|
||||
F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
|
||||
{
|
||||
self.app.update_view(handle, update)
|
||||
}
|
||||
@@ -2470,7 +2494,11 @@ impl<T: Entity> ModelHandle<T> {
|
||||
C: ReadModelWith,
|
||||
F: FnOnce(&T, &AppContext) -> S,
|
||||
{
|
||||
cx.read_model_with(self, read)
|
||||
let mut read = Some(read);
|
||||
cx.read_model_with(self, &mut |model, cx| {
|
||||
let read = read.take().unwrap();
|
||||
read(model, cx)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
|
||||
@@ -2478,7 +2506,11 @@ impl<T: Entity> ModelHandle<T> {
|
||||
C: UpdateModel,
|
||||
F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
|
||||
{
|
||||
cx.update_model(self, update)
|
||||
let mut update = Some(update);
|
||||
cx.update_model(self, &mut |model, cx| {
|
||||
let update = update.take().unwrap();
|
||||
update(model, cx)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn next_notification(&self, cx: &TestAppContext) -> impl Future<Output = ()> {
|
||||
@@ -2744,7 +2776,11 @@ impl<T: View> ViewHandle<T> {
|
||||
C: ReadViewWith,
|
||||
F: FnOnce(&T, &AppContext) -> S,
|
||||
{
|
||||
cx.read_view_with(self, read)
|
||||
let mut read = Some(read);
|
||||
cx.read_view_with(self, &mut |view, cx| {
|
||||
let read = read.take().unwrap();
|
||||
read(view, cx)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
|
||||
@@ -2752,7 +2788,11 @@ impl<T: View> ViewHandle<T> {
|
||||
C: UpdateView,
|
||||
F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
|
||||
{
|
||||
cx.update_view(self, update)
|
||||
let mut update = Some(update);
|
||||
cx.update_view(self, &mut |view, cx| {
|
||||
let update = update.take().unwrap();
|
||||
update(view, cx)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_focused(&self, cx: &AppContext) -> bool {
|
||||
|
||||
+135
-53
@@ -1,12 +1,12 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use async_task::Runnable;
|
||||
pub use async_task::Task;
|
||||
use backtrace::{Backtrace, BacktraceFmt, BytesOrWideString};
|
||||
use parking_lot::Mutex;
|
||||
use postage::{barrier, prelude::Stream as _};
|
||||
use rand::prelude::*;
|
||||
use smol::{channel, prelude::*, Executor, Timer};
|
||||
use std::{
|
||||
any::Any,
|
||||
fmt::{self, Debug},
|
||||
marker::PhantomData,
|
||||
mem,
|
||||
@@ -23,7 +23,10 @@ use std::{
|
||||
};
|
||||
use waker_fn::waker_fn;
|
||||
|
||||
use crate::{platform, util};
|
||||
use crate::{
|
||||
platform::{self, Dispatcher},
|
||||
util,
|
||||
};
|
||||
|
||||
pub enum Foreground {
|
||||
Platform {
|
||||
@@ -42,6 +45,24 @@ pub enum Background {
|
||||
},
|
||||
}
|
||||
|
||||
type AnyLocalFuture = Pin<Box<dyn 'static + Future<Output = Box<dyn Any + 'static>>>>;
|
||||
type AnyFuture = Pin<Box<dyn 'static + Send + Future<Output = Box<dyn Any + Send + 'static>>>>;
|
||||
type AnyTask = async_task::Task<Box<dyn Any + Send + 'static>>;
|
||||
type AnyLocalTask = async_task::Task<Box<dyn Any + 'static>>;
|
||||
|
||||
pub enum Task<T> {
|
||||
Local {
|
||||
any_task: AnyLocalTask,
|
||||
result_type: PhantomData<T>,
|
||||
},
|
||||
Send {
|
||||
any_task: AnyTask,
|
||||
result_type: PhantomData<T>,
|
||||
},
|
||||
}
|
||||
|
||||
unsafe impl<T: Send> Send for Task<T> {}
|
||||
|
||||
struct DeterministicState {
|
||||
rng: StdRng,
|
||||
seed: u64,
|
||||
@@ -77,11 +98,7 @@ impl Deterministic {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn_from_foreground<F, T>(&self, future: F) -> Task<T>
|
||||
where
|
||||
T: 'static,
|
||||
F: Future<Output = T> + 'static,
|
||||
{
|
||||
fn spawn_from_foreground(&self, future: AnyLocalFuture) -> AnyLocalTask {
|
||||
let backtrace = Backtrace::new_unresolved();
|
||||
let scheduled_once = AtomicBool::new(false);
|
||||
let state = self.state.clone();
|
||||
@@ -100,11 +117,7 @@ impl Deterministic {
|
||||
task
|
||||
}
|
||||
|
||||
pub fn spawn<F, T>(&self, future: F) -> Task<T>
|
||||
where
|
||||
T: 'static + Send,
|
||||
F: 'static + Send + Future<Output = T>,
|
||||
{
|
||||
fn spawn(&self, future: AnyFuture) -> AnyTask {
|
||||
let backtrace = Backtrace::new_unresolved();
|
||||
let state = self.state.clone();
|
||||
let unparker = self.parker.lock().unparker();
|
||||
@@ -119,13 +132,8 @@ impl Deterministic {
|
||||
task
|
||||
}
|
||||
|
||||
pub fn run<F, T>(&self, future: F) -> T
|
||||
where
|
||||
T: 'static,
|
||||
F: Future<Output = T> + 'static,
|
||||
{
|
||||
fn run(&self, mut future: AnyLocalFuture) -> Box<dyn Any> {
|
||||
let woken = Arc::new(AtomicBool::new(false));
|
||||
let mut future = Box::pin(future);
|
||||
loop {
|
||||
if let Some(result) = self.run_internal(woken.clone(), &mut future) {
|
||||
return result;
|
||||
@@ -142,16 +150,15 @@ impl Deterministic {
|
||||
|
||||
fn run_until_parked(&self) {
|
||||
let woken = Arc::new(AtomicBool::new(false));
|
||||
let future = std::future::pending::<()>();
|
||||
smol::pin!(future);
|
||||
self.run_internal(woken, future);
|
||||
let mut future = any_local_future(std::future::pending::<()>());
|
||||
self.run_internal(woken, &mut future);
|
||||
}
|
||||
|
||||
pub fn run_internal<F, T>(&self, woken: Arc<AtomicBool>, mut future: F) -> Option<T>
|
||||
where
|
||||
T: 'static,
|
||||
F: Future<Output = T> + Unpin,
|
||||
{
|
||||
fn run_internal(
|
||||
&self,
|
||||
woken: Arc<AtomicBool>,
|
||||
future: &mut AnyLocalFuture,
|
||||
) -> Option<Box<dyn Any>> {
|
||||
let unparker = self.parker.lock().unparker();
|
||||
let waker = waker_fn(move || {
|
||||
woken.store(true, SeqCst);
|
||||
@@ -205,13 +212,7 @@ impl Deterministic {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn block_on<F, T>(&self, future: F) -> Option<T>
|
||||
where
|
||||
T: 'static,
|
||||
F: Future<Output = T>,
|
||||
{
|
||||
smol::pin!(future);
|
||||
|
||||
fn block_on(&self, future: &mut AnyLocalFuture) -> Option<Box<dyn Any>> {
|
||||
let unparker = self.parker.lock().unparker();
|
||||
let waker = waker_fn(move || {
|
||||
unparker.unpark();
|
||||
@@ -396,25 +397,36 @@ impl Foreground {
|
||||
}
|
||||
|
||||
pub fn spawn<T: 'static>(&self, future: impl Future<Output = T> + 'static) -> Task<T> {
|
||||
match self {
|
||||
let future = any_local_future(future);
|
||||
let any_task = match self {
|
||||
Self::Deterministic(executor) => executor.spawn_from_foreground(future),
|
||||
Self::Platform { dispatcher, .. } => {
|
||||
let dispatcher = dispatcher.clone();
|
||||
let schedule = move |runnable: Runnable| dispatcher.run_on_main_thread(runnable);
|
||||
let (runnable, task) = async_task::spawn_local(future, schedule);
|
||||
runnable.schedule();
|
||||
task
|
||||
fn spawn_inner(
|
||||
future: AnyLocalFuture,
|
||||
dispatcher: &Arc<dyn Dispatcher>,
|
||||
) -> AnyLocalTask {
|
||||
let dispatcher = dispatcher.clone();
|
||||
let schedule =
|
||||
move |runnable: Runnable| dispatcher.run_on_main_thread(runnable);
|
||||
let (runnable, task) = async_task::spawn_local(future, schedule);
|
||||
runnable.schedule();
|
||||
task
|
||||
}
|
||||
spawn_inner(future, dispatcher)
|
||||
}
|
||||
Self::Test(executor) => executor.spawn(future),
|
||||
Self::Deterministic(executor) => executor.spawn_from_foreground(future),
|
||||
}
|
||||
};
|
||||
Task::local(any_task)
|
||||
}
|
||||
|
||||
pub fn run<T: 'static>(&self, future: impl 'static + Future<Output = T>) -> T {
|
||||
match self {
|
||||
let future = any_local_future(future);
|
||||
let any_value = match self {
|
||||
Self::Deterministic(executor) => executor.run(future),
|
||||
Self::Platform { .. } => panic!("you can't call run on a platform foreground executor"),
|
||||
Self::Test(executor) => smol::block_on(executor.run(future)),
|
||||
Self::Deterministic(executor) => executor.run(future),
|
||||
}
|
||||
};
|
||||
*any_value.downcast().unwrap()
|
||||
}
|
||||
|
||||
pub fn forbid_parking(&self) {
|
||||
@@ -500,29 +512,34 @@ impl Background {
|
||||
T: 'static + Send,
|
||||
F: Send + Future<Output = T> + 'static,
|
||||
{
|
||||
match self {
|
||||
let future = any_future(future);
|
||||
let any_task = match self {
|
||||
Self::Production { executor, .. } => executor.spawn(future),
|
||||
Self::Deterministic(executor) => executor.spawn(future),
|
||||
}
|
||||
};
|
||||
Task::send(any_task)
|
||||
}
|
||||
|
||||
pub fn block_with_timeout<F, T>(&self, timeout: Duration, mut future: F) -> Result<T, F>
|
||||
pub fn block_with_timeout<F, T>(
|
||||
&self,
|
||||
timeout: Duration,
|
||||
future: F,
|
||||
) -> Result<T, impl Future<Output = T>>
|
||||
where
|
||||
T: 'static,
|
||||
F: 'static + Unpin + Future<Output = T>,
|
||||
{
|
||||
let mut future = any_local_future(future);
|
||||
if !timeout.is_zero() {
|
||||
let output = match self {
|
||||
Self::Production { .. } => {
|
||||
smol::block_on(util::timeout(timeout, Pin::new(&mut future))).ok()
|
||||
}
|
||||
Self::Deterministic(executor) => executor.block_on(Pin::new(&mut future)),
|
||||
Self::Production { .. } => smol::block_on(util::timeout(timeout, &mut future)).ok(),
|
||||
Self::Deterministic(executor) => executor.block_on(&mut future),
|
||||
};
|
||||
if let Some(output) = output {
|
||||
return Ok(output);
|
||||
return Ok(*output.downcast().unwrap());
|
||||
}
|
||||
}
|
||||
Err(future)
|
||||
Err(async { *future.await.downcast().unwrap() })
|
||||
}
|
||||
|
||||
pub async fn scoped<'scope, F>(&self, scheduler: F)
|
||||
@@ -572,3 +589,68 @@ pub fn deterministic(seed: u64) -> (Rc<Foreground>, Arc<Background>) {
|
||||
Arc::new(Background::Deterministic(executor)),
|
||||
)
|
||||
}
|
||||
|
||||
impl<T> Task<T> {
|
||||
fn local(any_task: AnyLocalTask) -> Self {
|
||||
Self::Local {
|
||||
any_task,
|
||||
result_type: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn detach(self) {
|
||||
match self {
|
||||
Task::Local { any_task, .. } => any_task.detach(),
|
||||
Task::Send { any_task, .. } => any_task.detach(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send> Task<T> {
|
||||
fn send(any_task: AnyTask) -> Self {
|
||||
Self::Send {
|
||||
any_task,
|
||||
result_type: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug> fmt::Debug for Task<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Task::Local { any_task, .. } => any_task.fmt(f),
|
||||
Task::Send { any_task, .. } => any_task.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> Future for Task<T> {
|
||||
type Output = T;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
match unsafe { self.get_unchecked_mut() } {
|
||||
Task::Local { any_task, .. } => {
|
||||
any_task.poll(cx).map(|value| *value.downcast().unwrap())
|
||||
}
|
||||
Task::Send { any_task, .. } => {
|
||||
any_task.poll(cx).map(|value| *value.downcast().unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn any_future<T, F>(future: F) -> AnyFuture
|
||||
where
|
||||
T: 'static + Send,
|
||||
F: Future<Output = T> + Send + 'static,
|
||||
{
|
||||
async { Box::new(future.await) as Box<dyn Any + Send> }.boxed()
|
||||
}
|
||||
|
||||
fn any_local_future<T, F>(future: F) -> AnyLocalFuture
|
||||
where
|
||||
T: 'static,
|
||||
F: Future<Output = T> + 'static,
|
||||
{
|
||||
async { Box::new(future.await) as Box<dyn Any> }.boxed_local()
|
||||
}
|
||||
|
||||
+1
-11
@@ -7,7 +7,7 @@ use crate::{
|
||||
platform::Event,
|
||||
text_layout::TextLayoutCache,
|
||||
Action, AnyAction, AssetCache, ElementBox, Entity, FontSystem, ModelHandle, ReadModel,
|
||||
ReadView, Scene, UpdateView, View, ViewHandle,
|
||||
ReadView, Scene, View, ViewHandle,
|
||||
};
|
||||
use pathfinder_geometry::vector::{vec2f, Vector2F};
|
||||
use serde_json::json;
|
||||
@@ -264,16 +264,6 @@ impl<'a> ReadView for LayoutContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> UpdateView for LayoutContext<'a> {
|
||||
fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
|
||||
where
|
||||
T: View,
|
||||
F: FnOnce(&mut T, &mut crate::ViewContext<T>) -> S,
|
||||
{
|
||||
self.app.update_view(handle, update)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ReadModel for LayoutContext<'a> {
|
||||
fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
|
||||
self.app.read_model(handle)
|
||||
|
||||
+100
-87
@@ -1,6 +1,6 @@
|
||||
use super::*;
|
||||
use arrayvec::ArrayVec;
|
||||
use std::{cmp::Ordering, sync::Arc};
|
||||
use std::{cmp::Ordering, mem, sync::Arc};
|
||||
|
||||
#[derive(Clone)]
|
||||
struct StackEntry<'a, T: Item, D> {
|
||||
@@ -324,7 +324,7 @@ where
|
||||
Target: SeekTarget<'a, T::Summary, D>,
|
||||
{
|
||||
self.reset();
|
||||
self.seek_internal::<_, ()>(pos, bias, &mut SeekAggregate::None, cx)
|
||||
self.seek_internal(pos, bias, &mut (), cx)
|
||||
}
|
||||
|
||||
pub fn seek_forward<Target>(
|
||||
@@ -336,7 +336,7 @@ where
|
||||
where
|
||||
Target: SeekTarget<'a, T::Summary, D>,
|
||||
{
|
||||
self.seek_internal::<_, ()>(pos, bias, &mut SeekAggregate::None, cx)
|
||||
self.seek_internal(pos, bias, &mut (), cx)
|
||||
}
|
||||
|
||||
pub fn slice<Target>(
|
||||
@@ -348,23 +348,18 @@ where
|
||||
where
|
||||
Target: SeekTarget<'a, T::Summary, D>,
|
||||
{
|
||||
let mut slice = SeekAggregate::Slice(SumTree::new());
|
||||
self.seek_internal::<_, ()>(end, bias, &mut slice, cx);
|
||||
if let SeekAggregate::Slice(slice) = slice {
|
||||
slice
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
let mut slice = SliceSeekAggregate {
|
||||
tree: SumTree::new(),
|
||||
leaf_items: ArrayVec::new(),
|
||||
leaf_item_summaries: ArrayVec::new(),
|
||||
leaf_summary: T::Summary::default(),
|
||||
};
|
||||
self.seek_internal(end, bias, &mut slice, cx);
|
||||
slice.tree
|
||||
}
|
||||
|
||||
pub fn suffix(&mut self, cx: &<T::Summary as Summary>::Context) -> SumTree<T> {
|
||||
let mut slice = SeekAggregate::Slice(SumTree::new());
|
||||
self.seek_internal::<_, ()>(&End::new(), Bias::Right, &mut slice, cx);
|
||||
if let SeekAggregate::Slice(slice) = slice {
|
||||
slice
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
self.slice(&End::new(), Bias::Right, cx)
|
||||
}
|
||||
|
||||
pub fn summary<Target, Output>(
|
||||
@@ -377,26 +372,18 @@ where
|
||||
Target: SeekTarget<'a, T::Summary, D>,
|
||||
Output: Dimension<'a, T::Summary>,
|
||||
{
|
||||
let mut summary = SeekAggregate::Summary(Output::default());
|
||||
let mut summary = SummarySeekAggregate(Output::default());
|
||||
self.seek_internal(end, bias, &mut summary, cx);
|
||||
if let SeekAggregate::Summary(summary) = summary {
|
||||
summary
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
summary.0
|
||||
}
|
||||
|
||||
fn seek_internal<Target, Output>(
|
||||
fn seek_internal(
|
||||
&mut self,
|
||||
target: &Target,
|
||||
target: &dyn SeekTarget<'a, T::Summary, D>,
|
||||
bias: Bias,
|
||||
aggregate: &mut SeekAggregate<T, Output>,
|
||||
aggregate: &mut dyn SeekAggregate<'a, T>,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> bool
|
||||
where
|
||||
Target: SeekTarget<'a, T::Summary, D>,
|
||||
Output: Dimension<'a, T::Summary>,
|
||||
{
|
||||
) -> bool {
|
||||
debug_assert!(
|
||||
target.cmp(&self.position, cx) >= Ordering::Equal,
|
||||
"cannot seek backward from {:?} to {:?}",
|
||||
@@ -437,15 +424,7 @@ where
|
||||
|| (comparison == Ordering::Equal && bias == Bias::Right)
|
||||
{
|
||||
self.position = child_end;
|
||||
match aggregate {
|
||||
SeekAggregate::None => {}
|
||||
SeekAggregate::Slice(slice) => {
|
||||
slice.push_tree(child_tree.clone(), cx);
|
||||
}
|
||||
SeekAggregate::Summary(summary) => {
|
||||
summary.add_summary(child_summary, cx);
|
||||
}
|
||||
}
|
||||
aggregate.push_tree(child_tree, child_summary, cx);
|
||||
entry.index += 1;
|
||||
entry.position = self.position.clone();
|
||||
} else {
|
||||
@@ -464,12 +443,7 @@ where
|
||||
ref item_summaries,
|
||||
..
|
||||
} => {
|
||||
let mut slice_items = ArrayVec::<T, { 2 * TREE_BASE }>::new();
|
||||
let mut slice_item_summaries = ArrayVec::<T::Summary, { 2 * TREE_BASE }>::new();
|
||||
let mut slice_items_summary = match aggregate {
|
||||
SeekAggregate::Slice(_) => Some(T::Summary::default()),
|
||||
_ => None,
|
||||
};
|
||||
aggregate.begin_leaf();
|
||||
|
||||
for (item, item_summary) in items[entry.index..]
|
||||
.iter()
|
||||
@@ -483,49 +457,15 @@ where
|
||||
|| (comparison == Ordering::Equal && bias == Bias::Right)
|
||||
{
|
||||
self.position = child_end;
|
||||
match aggregate {
|
||||
SeekAggregate::None => {}
|
||||
SeekAggregate::Slice(_) => {
|
||||
slice_items.push(item.clone());
|
||||
slice_item_summaries.push(item_summary.clone());
|
||||
<T::Summary as Summary>::add_summary(
|
||||
slice_items_summary.as_mut().unwrap(),
|
||||
item_summary,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
SeekAggregate::Summary(summary) => {
|
||||
summary.add_summary(item_summary, cx);
|
||||
}
|
||||
}
|
||||
aggregate.push_item(item, item_summary, cx);
|
||||
entry.index += 1;
|
||||
} else {
|
||||
if let SeekAggregate::Slice(slice) = aggregate {
|
||||
slice.push_tree(
|
||||
SumTree(Arc::new(Node::Leaf {
|
||||
summary: slice_items_summary.unwrap(),
|
||||
items: slice_items,
|
||||
item_summaries: slice_item_summaries,
|
||||
})),
|
||||
cx,
|
||||
);
|
||||
}
|
||||
aggregate.end_leaf(cx);
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
|
||||
if let SeekAggregate::Slice(slice) = aggregate {
|
||||
if !slice_items.is_empty() {
|
||||
slice.push_tree(
|
||||
SumTree(Arc::new(Node::Leaf {
|
||||
summary: slice_items_summary.unwrap(),
|
||||
items: slice_items,
|
||||
item_summaries: slice_item_summaries,
|
||||
})),
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
aggregate.end_leaf(cx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -625,8 +565,81 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
enum SeekAggregate<T: Item, D> {
|
||||
None,
|
||||
Slice(SumTree<T>),
|
||||
Summary(D),
|
||||
trait SeekAggregate<'a, T: Item> {
|
||||
fn begin_leaf(&mut self);
|
||||
fn end_leaf(&mut self, cx: &<T::Summary as Summary>::Context);
|
||||
fn push_item(
|
||||
&mut self,
|
||||
item: &'a T,
|
||||
summary: &'a T::Summary,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
);
|
||||
fn push_tree(
|
||||
&mut self,
|
||||
tree: &'a SumTree<T>,
|
||||
summary: &'a T::Summary,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
);
|
||||
}
|
||||
|
||||
struct SliceSeekAggregate<T: Item> {
|
||||
tree: SumTree<T>,
|
||||
leaf_items: ArrayVec<T, { 2 * TREE_BASE }>,
|
||||
leaf_item_summaries: ArrayVec<T::Summary, { 2 * TREE_BASE }>,
|
||||
leaf_summary: T::Summary,
|
||||
}
|
||||
|
||||
struct SummarySeekAggregate<D>(D);
|
||||
|
||||
impl<'a, T: Item> SeekAggregate<'a, T> for () {
|
||||
fn begin_leaf(&mut self) {}
|
||||
fn end_leaf(&mut self, _: &<T::Summary as Summary>::Context) {}
|
||||
fn push_item(&mut self, _: &T, _: &T::Summary, _: &<T::Summary as Summary>::Context) {}
|
||||
fn push_tree(&mut self, _: &SumTree<T>, _: &T::Summary, _: &<T::Summary as Summary>::Context) {}
|
||||
}
|
||||
|
||||
impl<'a, T: Item> SeekAggregate<'a, T> for SliceSeekAggregate<T> {
|
||||
fn begin_leaf(&mut self) {}
|
||||
fn end_leaf(&mut self, cx: &<T::Summary as Summary>::Context) {
|
||||
self.tree.push_tree(
|
||||
SumTree(Arc::new(Node::Leaf {
|
||||
summary: mem::take(&mut self.leaf_summary),
|
||||
items: mem::take(&mut self.leaf_items),
|
||||
item_summaries: mem::take(&mut self.leaf_item_summaries),
|
||||
})),
|
||||
cx,
|
||||
);
|
||||
}
|
||||
fn push_item(&mut self, item: &T, summary: &T::Summary, cx: &<T::Summary as Summary>::Context) {
|
||||
self.leaf_items.push(item.clone());
|
||||
self.leaf_item_summaries.push(summary.clone());
|
||||
Summary::add_summary(&mut self.leaf_summary, summary, cx);
|
||||
}
|
||||
fn push_tree(
|
||||
&mut self,
|
||||
tree: &SumTree<T>,
|
||||
_: &T::Summary,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) {
|
||||
self.tree.push_tree(tree.clone(), cx);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Item, D> SeekAggregate<'a, T> for SummarySeekAggregate<D>
|
||||
where
|
||||
D: Dimension<'a, T::Summary>,
|
||||
{
|
||||
fn begin_leaf(&mut self) {}
|
||||
fn end_leaf(&mut self, _: &<T::Summary as Summary>::Context) {}
|
||||
fn push_item(&mut self, _: &T, summary: &'a T::Summary, cx: &<T::Summary as Summary>::Context) {
|
||||
self.0.add_summary(summary, cx);
|
||||
}
|
||||
fn push_tree(
|
||||
&mut self,
|
||||
_: &SumTree<T>,
|
||||
summary: &'a T::Summary,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) {
|
||||
self.0.add_summary(summary, cx);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user