cranpose_core/platform.rs
1//! Platform abstraction traits for Compose runtime services.
2//!
3//! These traits allow Compose to delegate scheduling and clock
4//! responsibilities to the host platform, enabling integration with
5//! different environments without depending directly on `std` APIs.
6
7/// Schedules work for the Compose runtime.
8///
9/// Implementations are responsible for triggering frame processing and
10/// executing background tasks on behalf of Compose.
11#[cfg(not(target_arch = "wasm32"))]
12pub trait RuntimeScheduler: Send + Sync {
13 /// Request that the host schedule a new frame.
14 fn schedule_frame(&self);
15}
16
17/// Schedules work for the Compose runtime on single-threaded wasm hosts.
18#[cfg(target_arch = "wasm32")]
19pub trait RuntimeScheduler {
20 /// Request that the host schedule a new frame.
21 fn schedule_frame(&self);
22}
23
24/// Shared handle to a [`RuntimeScheduler`].
25///
26/// A native host wakes the runtime from other threads (a background task
27/// finishing, a timer firing), so the handle has to be an atomically
28/// reference-counted pointer to a `Send + Sync` scheduler. A wasm host runs
29/// everything on a single thread and its scheduler holds JS values that can
30/// only ever live on that thread, so it cannot be `Send + Sync`; wrapping it
31/// in `Arc` there would buy synchronisation the target has no use for, so a
32/// plain `Rc` is used instead.
33#[cfg(not(target_arch = "wasm32"))]
34pub type SchedulerRef = std::sync::Arc<dyn RuntimeScheduler>;
35
36/// Shared handle to a [`RuntimeScheduler`]. See the native definition for why
37/// this is `Rc` on wasm instead of `Arc`.
38#[cfg(target_arch = "wasm32")]
39pub type SchedulerRef = std::rc::Rc<dyn RuntimeScheduler>;
40
41/// Wraps `scheduler` in a [`SchedulerRef`].
42///
43/// A trait-object alias cannot expose its own `new` the way a concrete type
44/// can (`Arc<dyn Trait>::new` has no `Sized` value to accept), so this is the
45/// one place that picks `Arc` on native and `Rc` on wasm; callers that need a
46/// [`SchedulerRef`] from a concrete scheduler go through this instead of
47/// repeating that choice.
48#[cfg(not(target_arch = "wasm32"))]
49pub fn scheduler_ref<S: RuntimeScheduler + 'static>(scheduler: S) -> SchedulerRef {
50 std::sync::Arc::new(scheduler)
51}
52
53/// See the native definition of [`scheduler_ref`] for why this is `Rc` on wasm.
54#[cfg(target_arch = "wasm32")]
55pub fn scheduler_ref<S: RuntimeScheduler + 'static>(scheduler: S) -> SchedulerRef {
56 std::rc::Rc::new(scheduler)
57}
58
59/// Provides timing information for the runtime.
60pub trait Clock: Send + Sync {
61 /// Instant type produced by this clock implementation.
62 type Instant: Copy + Send + Sync;
63
64 /// Returns the current instant.
65 fn now(&self) -> Self::Instant;
66
67 /// Returns the number of milliseconds elapsed since `since`.
68 fn elapsed_millis(&self, since: Self::Instant) -> u64;
69}