kozan_scheduler/lib.rs
1//! `kozan-scheduler` — Task scheduler and async executor for Kozan.
2//!
3//! Like Chrome's `base/task/` + `blink/platform/scheduler/`.
4//! Standalone crate — zero dependency on `kozan-core`.
5//!
6//! # Architecture
7//!
8//! ```text
9//! Scheduler (MainThreadScheduler — the event loop)
10//! ├── TaskQueueManager (SequenceManager — priority picker)
11//! │ └── TaskQueue × 6 (one per priority level)
12//! ├── MicrotaskQueue (drain after each macrotask)
13//! ├── LocalExecutor (!Send async runtime)
14//! ├── FrameScheduler (vsync-driven frame timing)
15//! └── WakeReceiver (cross-thread task delivery)
16//! ```
17//!
18//! # Event loop algorithm (HTML spec)
19//!
20//! ```text
21//! loop {
22//! 1. Receive cross-thread tasks
23//! 2. Promote delayed tasks
24//! 3. Poll async executor
25//! 4. Pick ONE macrotask → run
26//! 5. Drain ALL microtasks
27//! 6. If frame due → callbacks → style → layout → paint
28//! 7. Park until next event
29//! }
30//! ```
31
32pub mod executor;
33pub mod frame;
34pub mod microtask;
35pub mod queue;
36pub mod scheduler;
37pub mod task;
38pub mod timer;
39pub mod waker;
40
41// Re-exports: the main types users need.
42pub use executor::{LocalExecutor, TaskId};
43pub use frame::{FrameInfo, FrameScheduler, FrameTiming};
44pub use microtask::{Microtask, MicrotaskQueue};
45pub use queue::{TaskQueue, TaskQueueManager};
46pub use scheduler::{Scheduler, TickResult};
47pub use task::{Task, TaskPriority};
48pub use waker::{CrossThreadTask, SendError, WakeReceiver, WakeSender, cross_thread_channel};
49
50// ---- Compile-time Send/Sync guarantees ----
51//
52// These assertions prevent accidental breakage of threading contracts.
53// A refactor that removes PhantomData or changes a field type will
54// fail to compile here — not silently at runtime.
55
56#[cfg(test)]
57mod send_sync_tests {
58 use super::*;
59
60 // Must be Send + Clone (shared across background threads).
61 const _: fn() = || {
62 fn assert_send_clone<T: Send + Clone>() {}
63 assert_send_clone::<WakeSender>();
64 };
65
66 // Must be Send (crosses thread boundary).
67 const _: fn() = || {
68 fn assert_send<T: Send>() {}
69 assert_send::<CrossThreadTask>();
70 };
71
72 // Must NOT be Send (stays on window thread).
73 // Scheduler contains WakeReceiver which has PhantomData<*const ()>.
74 // If this compiles, our !Send guarantee is broken.
75 // We verify !Send via a negative test that would fail to compile
76 // if Scheduler were Send. Unfortunately Rust doesn't have
77 // static_assert_not_impl, so we test this at runtime:
78 #[test]
79 fn send_types_are_send() {
80 fn assert_send<T: Send>() {}
81 assert_send::<WakeSender>();
82 assert_send::<CrossThreadTask>();
83 }
84}