Fix Compositor concurrent initialization

It seems that initializing the compositor in a
different thread can cause issues in some environments.
This commit is contained in:
Héctor Ramón Jiménez 2025-04-02 20:33:22 +02:00
parent d203392c9d
commit 1b22d7d5fc
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
8 changed files with 37 additions and 14 deletions

View file

@ -12,6 +12,10 @@ impl crate::Executor for Executor {
fn spawn(&self, future: impl Future<Output = ()> + Send + 'static) { fn spawn(&self, future: impl Future<Output = ()> + Send + 'static) {
smol::spawn(future).detach(); smol::spawn(future).detach();
} }
fn block_on<T>(&self, future: impl Future<Output = T>) -> T {
smol::block_on(future)
}
} }
pub mod time { pub mod time {

View file

@ -11,6 +11,10 @@ impl crate::Executor for Executor {
fn spawn(&self, future: impl Future<Output = ()> + Send + 'static) { fn spawn(&self, future: impl Future<Output = ()> + Send + 'static) {
self.spawn_ok(future); self.spawn_ok(future);
} }
fn block_on<T>(&self, future: impl Future<Output = T>) -> T {
futures::executor::block_on(future)
}
} }
pub mod time { pub mod time {

View file

@ -17,6 +17,10 @@ impl crate::Executor for Executor {
let _guard = tokio::runtime::Runtime::enter(self); let _guard = tokio::runtime::Runtime::enter(self);
f() f()
} }
fn block_on<T>(&self, future: impl Future<Output = T>) -> T {
self.block_on(future)
}
} }
pub mod time { pub mod time {

View file

@ -11,6 +11,11 @@ impl crate::Executor for Executor {
} }
fn spawn(&self, _future: impl Future<Output = ()> + MaybeSend + 'static) {} fn spawn(&self, _future: impl Future<Output = ()> + MaybeSend + 'static) {}
#[cfg(not(target_arch = "wasm32"))]
fn block_on<T>(&self, _future: impl Future<Output = T>) -> T {
unimplemented!()
}
} }
pub mod time { pub mod time {

View file

@ -11,6 +11,10 @@ pub trait Executor: Sized {
/// Spawns a future in the [`Executor`]. /// Spawns a future in the [`Executor`].
fn spawn(&self, future: impl Future<Output = ()> + MaybeSend + 'static); fn spawn(&self, future: impl Future<Output = ()> + MaybeSend + 'static);
/// Runs a future to completion in the current thread within the [`Executor`].
#[cfg(not(target_arch = "wasm32"))]
fn block_on<T>(&self, future: impl Future<Output = T>) -> T;
/// Runs the given closure inside the [`Executor`]. /// Runs the given closure inside the [`Executor`].
/// ///
/// Some executors, like `tokio`, require some global state to be in place /// Some executors, like `tokio`, require some global state to be in place

View file

@ -50,12 +50,10 @@ where
self.executor.enter(f) self.executor.enter(f)
} }
/// Spawns a [`Future`] in the [`Runtime`]. /// Runs a future to completion in the current thread within the [`Runtime`].
pub fn spawn( #[cfg(not(target_arch = "wasm32"))]
&mut self, pub fn block_on<T>(&mut self, future: impl Future<Output = T>) -> T {
future: impl Future<Output = ()> + MaybeSend + 'static, self.executor.block_on(future)
) {
self.executor.spawn(future);
} }
/// Runs a [`Stream`] in the [`Runtime`] until completion. /// Runs a [`Stream`] in the [`Runtime`] until completion.

View file

@ -10,7 +10,7 @@ use thiserror::Error;
use std::borrow::Cow; use std::borrow::Cow;
/// A graphics compositor that can draw to windows. /// A graphics compositor that can draw to windows.
pub trait Compositor: Sized + MaybeSend { pub trait Compositor: Sized {
/// The iced renderer of the backend. /// The iced renderer of the backend.
type Renderer; type Renderer;
@ -21,7 +21,7 @@ pub trait Compositor: Sized + MaybeSend {
fn new<W: Window + Clone>( fn new<W: Window + Clone>(
settings: Settings, settings: Settings,
compatible_window: W, compatible_window: W,
) -> impl Future<Output = Result<Self, Error>> + MaybeSend { ) -> impl Future<Output = Result<Self, Error>> {
Self::with_backend(settings, compatible_window, None) Self::with_backend(settings, compatible_window, None)
} }
@ -33,7 +33,7 @@ pub trait Compositor: Sized + MaybeSend {
_settings: Settings, _settings: Settings,
_compatible_window: W, _compatible_window: W,
_backend: Option<&str>, _backend: Option<&str>,
) -> impl Future<Output = Result<Self, Error>> + MaybeSend; ) -> impl Future<Output = Result<Self, Error>>;
/// Creates a [`Self::Renderer`] for the [`Compositor`]. /// Creates a [`Self::Renderer`] for the [`Compositor`].
fn create_renderer(&self) -> Self::Renderer; fn create_renderer(&self) -> Self::Renderer;

View file

@ -18,7 +18,7 @@ use crate::futures::futures::channel::oneshot;
use crate::futures::futures::task; use crate::futures::futures::task;
use crate::futures::futures::{Future, StreamExt}; use crate::futures::futures::{Future, StreamExt};
use crate::futures::subscription::{self, Subscription}; use crate::futures::subscription::{self, Subscription};
use crate::futures::{Executor, MaybeSend, Runtime}; use crate::futures::{Executor, Runtime};
use crate::graphics; use crate::graphics;
use crate::graphics::{Compositor, compositor}; use crate::graphics::{Compositor, compositor};
use crate::runtime::Debug; use crate::runtime::Debug;
@ -149,7 +149,7 @@ pub fn run<P, C>(
) -> Result<(), Error> ) -> Result<(), Error>
where where
P: Program + 'static, P: Program + 'static,
C: Compositor<Renderer = P::Renderer> + MaybeSend + 'static, C: Compositor<Renderer = P::Renderer> + 'static,
P::Theme: theme::Base, P::Theme: theme::Base,
{ {
use winit::event_loop::EventLoop; use winit::event_loop::EventLoop;
@ -560,7 +560,7 @@ async fn run_instance<P, C>(
default_fonts: Vec<Cow<'static, [u8]>>, default_fonts: Vec<Cow<'static, [u8]>>,
) where ) where
P: Program + 'static, P: Program + 'static,
C: Compositor<Renderer = P::Renderer> + MaybeSend + 'static, C: Compositor<Renderer = P::Renderer> + 'static,
P::Theme: theme::Base, P::Theme: theme::Base,
{ {
use winit::event; use winit::event;
@ -636,7 +636,11 @@ async fn run_instance<P, C>(
} }
}; };
runtime.spawn(create_compositor); #[cfg(target_arch = "wasm32")]
wasm_bindgen_futures::spawn_local(create_compositor);
#[cfg(not(target_arch = "wasm32"))]
runtime.block_on(create_compositor);
match compositor_receiver match compositor_receiver
.await .await
@ -648,7 +652,7 @@ async fn run_instance<P, C>(
Err(error) => { Err(error) => {
let _ = control_sender let _ = control_sender
.start_send(Control::Crash(error.into())); .start_send(Control::Crash(error.into()));
break; continue;
} }
} }
} }