smudge-core 0.1.0

Widget tree, reactive bindings, layout, paint and damage tracking for the Smudge GUI library
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
//! The reactive runtime: signals, memos, effects and owners driven by the frame.
//!
//! The core is a small signal engine written for Smudge. It is single-threaded
//! and stores everything in one arena per thread. A signal write marks the
//! effects it reaches and queues them; the effects run when the frame calls
//! [`flush`], in the order they were woken, and writes made by an effect are
//! picked up by the same flush. Nothing runs between flushes.
//!
//! Every thread owns its own runtime, so effects on two threads never share
//! state. There is no executor to install and nothing to poll: call [`init`]
//! if you want the runtime to exist before the first signal, but creating a
//! signal does it too.
//!
//! A wake is reported to the callback set by [`set_wake_callback`], which is
//! how the platform learns that the next frame has work to do. The callback
//! belongs to the owner tree it was set under, so two apps on one thread each
//! get their own redraw requests. It runs on the first wake of its tree after
//! a flush and not again until the next flush ends. A write inside a flush
//! that wakes a tree the flush already serves asks for nothing, and one that
//! wakes another tree asks that tree for a redraw. While an app runs the
//! part of its frame that flushes until no effect is left, its tree asks for
//! nothing either, because the frame runs what the write woke. A wake is reported on the
//! thread that writes the signal, so write signals only on the thread that
//! runs their effects.
//!
//! ## Semantics
//!
//! - An effect runs once synchronously when it is created, and again from a
//!   flush after a source it read changed.
//! - An effect re-tracks its sources on every run, so conditional reads work.
//! - A memo recomputes when read after a source changed, and stops
//!   propagation when its new value compares equal. Memos are therefore
//!   glitch-free: a reader never sees a memo that disagrees with its sources.
//! - Effects are not glitch-free across effect-to-effect writes: an effect
//!   that reads what another effect writes sees whichever value the wake
//!   order gives it. Put a memo in between when that matters.
//! - An effect that runs more than a fixed number of times in one flush is a
//!   cycle. Debug builds panic; release builds stop running it for that
//!   flush, so the frame finishes.
//! - An effect whose body panics stays subscribed and runs again on the next
//!   write to a source it reached.
//! - Cleaning up an owner stops its effects and disposes its signals, children
//!   first. Dropping the last handle to an owner cleans it up too, so mount
//!   and unmount cycles return all of their memory.
//!
//! The reactive API is defined here, so a widget imports it from one place.
//! Types are at the module root and the traits that give them their methods
//! are in [`prelude`].
//!
//! ```
//! use smudge_core::reactive::{self, Owner, RenderEffect, prelude::*};
//! use std::cell::Cell;
//! use std::rc::Rc;
//!
//! reactive::init();
//! let owner = Owner::new();
//! owner.set();
//!
//! let (count, set_count) = reactive::signal_local(0u32);
//! let seen = Rc::new(Cell::new(0u32));
//! let recorder = Rc::clone(&seen);
//! let _effect = RenderEffect::new(move || recorder.set(count.get()));
//!
//! set_count.set(1);
//! assert_eq!(seen.get(), 0, "the write waits for the frame");
//!
//! reactive::flush();
//! assert_eq!(seen.get(), 1);
//! ```

use std::any::TypeId;
use std::cell::{Cell, RefCell};
use std::rc::{Rc, Weak};

pub(crate) mod runtime;

use runtime::{CurrentOwnerGuard, EffectCell, MemoData, NodeId, OwnerData, OwnerState, SignalData};

/// Installs the runtime on the calling thread.
///
/// Creating a signal, memo, effect or owner does this implicitly, so calling
/// `init` is never required. It exists so a thread can state that it runs the
/// reactive runtime, and so older call sites keep working. Calling it again
/// does nothing.
///
/// # Examples
///
/// ```
/// use smudge_core::reactive;
///
/// reactive::init();
/// assert!(!reactive::flush(), "nothing was woken");
/// ```
pub fn init() {
    runtime::with_runtime(|_| {});
}

/// Runs every effect woken since the last call, in the order they were woken,
/// and returns whether any effect ran.
///
/// Call this once per frame, before reading the updates that effects
/// produced. A write made while the flush runs has its effect run in the same
/// call, so the return value covers everything that write set off.
///
/// Does nothing and returns `false` when called from inside a running flush,
/// because that flush already drains the queue.
///
/// # Examples
///
/// ```
/// use smudge_core::reactive::{self, Owner, RenderEffect, prelude::*};
///
/// let owner = Owner::new();
/// owner.set();
/// let (count, set_count) = reactive::signal_local(0u32);
/// let _effect = RenderEffect::new(move || count.get());
///
/// assert!(!reactive::flush(), "the creation run is not a flush");
/// set_count.set(1);
/// assert!(reactive::flush(), "the write woke the effect");
/// assert!(!reactive::flush(), "nothing was woken since");
/// ```
pub fn flush() -> bool {
    runtime::flush()
}

/// Sets the callback that a wake between flushes runs to request a redraw.
///
/// The callback is stored on the root scope of the current owner tree, which
/// is the app whose owner is current. When no owner is current it is stored on
/// the thread's default scope. Replaces any previous callback of that scope.
///
/// The callback runs on the first wake of its tree after a flush and not
/// again until the next flush ends, so a frame that writes many signals
/// requests one redraw. A wake that arrives during a flush asks for nothing
/// when the tree already has an effect in that flush, because the flush
/// applies the write itself.
///
/// A wake is reported on the thread that writes the signal, so write signals
/// only on the thread that runs their effects.
///
/// # Examples
///
/// ```
/// use smudge_core::reactive::{self, Owner, RenderEffect, prelude::*};
/// use std::cell::Cell;
/// use std::rc::Rc;
///
/// let owner = Owner::new();
/// owner.set();
/// let redraws = Rc::new(Cell::new(0u32));
/// let counter = Rc::clone(&redraws);
/// reactive::set_wake_callback(move || counter.set(counter.get() + 1));
///
/// let (count, set_count) = reactive::signal_local(0u32);
/// let _effect = RenderEffect::new(move || count.get());
/// reactive::flush();
///
/// set_count.set(1);
/// assert_eq!(redraws.get(), 1);
/// ```
pub fn set_wake_callback(callback: impl Fn() + 'static) {
    // The previous callback drops after the runtime is released, so its drop
    // may enter the runtime.
    let scope = runtime::with_runtime(|runtime| runtime.current_scope());
    scope.wake.replace(Some(Rc::new(callback)));
}

/// The traits and constructors that signals, memos and owners need.
///
/// Import this module with a glob to call `.get()`, `.set()` and `.update()`
/// on reactive values, to read them with or without tracking, and to create
/// signals and provide context.
pub mod prelude {
    pub use super::{Get, Read, Set, Update, With, provide_context, signal_local, use_context};
}

/// Applies a closure to a reactive value, tracking it as a source.
pub trait With<T: ?Sized + 'static> {
    /// Applies `fun` to the current value and returns its result.
    ///
    /// When an effect or a memo is running, the value becomes one of its
    /// sources and a later change wakes it.
    fn with<U>(&self, fun: impl FnOnce(&T) -> U) -> U;
}

/// Applies a closure to a reactive value without tracking it.
pub trait Read<T: ?Sized + 'static> {
    /// Applies `fun` to the current value and returns its result.
    ///
    /// No source is recorded, so a later change wakes nothing through this
    /// read.
    fn read<U>(&self, fun: impl FnOnce(&T) -> U) -> U;
}

/// Clones the value of a reactive value, tracking it as a source.
pub trait Get<T: Clone + 'static>: With<T> {
    /// Returns a clone of the current value.
    fn get(&self) -> T {
        self.with(T::clone)
    }
}

impl<S, T> Get<T> for S
where
    S: With<T> + ?Sized,
    T: Clone + 'static,
{
}

/// Updates the value of a reactive value in place and notifies subscribers.
pub trait Update<T: 'static> {
    /// Applies `fun` to the value and notifies subscribers that it changed,
    /// whether or not `fun` changed anything.
    ///
    /// # Panics
    ///
    /// Panics when the value is already mutably borrowed, which happens when
    /// `fun` reads the same value.
    fn update<U>(&self, fun: impl FnOnce(&mut T) -> U) -> U;
}

/// Replaces the value of a reactive value and notifies subscribers.
pub trait Set<T: 'static>: Update<T> {
    /// Replaces the value and notifies subscribers, whether or not the new
    /// value compares equal to the old one.
    fn set(&self, value: T) {
        self.update(|slot| *slot = value);
    }
}

impl<S, T> Set<T> for S
where
    S: Update<T> + ?Sized,
    T: 'static,
{
}

/// A signal that can be read and written.
///
/// Created with [`RwSignal::new`], or split into a [`ReadSignal`] and a
/// [`WriteSignal`] by [`signal_local`]. Cloning the handle is cheap, and
/// every clone names the same signal.
pub struct RwSignal<T> {
    /// The value and the node that carries the subscribers.
    data: Rc<SignalData<T>>,
}

impl<T: 'static> RwSignal<T> {
    /// Creates a signal holding `value`, under the current owner.
    ///
    /// The signal is disposed when that owner is cleaned up. Handles that
    /// outlive it keep the value readable but notify nothing. With no current
    /// owner nothing disposes it, and its entry in the runtime stays until the
    /// thread ends.
    pub fn new(value: T) -> RwSignal<T> {
        let node = runtime::with_runtime(runtime::Runtime::new_signal);
        RwSignal {
            data: Rc::new(SignalData {
                value: RefCell::new(value),
                node: Cell::new(node),
            }),
        }
    }
}

impl<T: 'static> Clone for RwSignal<T> {
    fn clone(&self) -> RwSignal<T> {
        RwSignal {
            data: Rc::clone(&self.data),
        }
    }
}

impl<T: 'static> Clone for ReadSignal<T> {
    fn clone(&self) -> ReadSignal<T> {
        ReadSignal {
            data: Rc::clone(&self.data),
        }
    }
}

impl<T: 'static> Clone for WriteSignal<T> {
    fn clone(&self) -> WriteSignal<T> {
        WriteSignal {
            data: Rc::clone(&self.data),
        }
    }
}

impl<T: 'static> Clone for Memo<T> {
    fn clone(&self) -> Memo<T> {
        Memo {
            data: Rc::clone(&self.data),
        }
    }
}

impl<T: 'static> With<T> for RwSignal<T> {
    fn with<U>(&self, fun: impl FnOnce(&T) -> U) -> U {
        runtime::track_read(self.data.node.get());
        fun(&self.data.value.borrow())
    }
}

impl<T: 'static> Read<T> for RwSignal<T> {
    fn read<U>(&self, fun: impl FnOnce(&T) -> U) -> U {
        fun(&self.data.value.borrow())
    }
}

impl<T: 'static> Update<T> for RwSignal<T> {
    fn update<U>(&self, fun: impl FnOnce(&mut T) -> U) -> U {
        let result = fun(&mut self.data.value.borrow_mut());
        let wake = runtime::with_runtime(|runtime| runtime.notify(self.data.node.get()));
        runtime::fire_wakes(wake);
        result
    }
}

/// The read half of a signal. Cloning the handle is cheap, and every clone
/// names the same value.
pub struct ReadSignal<T> {
    /// The value and the node that carries the subscribers.
    data: Rc<SignalData<T>>,
}

impl<T: 'static> With<T> for ReadSignal<T> {
    fn with<U>(&self, fun: impl FnOnce(&T) -> U) -> U {
        runtime::track_read(self.data.node.get());
        fun(&self.data.value.borrow())
    }
}

impl<T: 'static> Read<T> for ReadSignal<T> {
    fn read<U>(&self, fun: impl FnOnce(&T) -> U) -> U {
        fun(&self.data.value.borrow())
    }
}

/// The write half of a signal. Cloning the handle is cheap, and every clone
/// writes the same value.
pub struct WriteSignal<T> {
    /// The value and the node that carries the subscribers.
    data: Rc<SignalData<T>>,
}

impl<T: 'static> Update<T> for WriteSignal<T> {
    fn update<U>(&self, fun: impl FnOnce(&mut T) -> U) -> U {
        let result = fun(&mut self.data.value.borrow_mut());
        let wake = runtime::with_runtime(|runtime| runtime.notify(self.data.node.get()));
        runtime::fire_wakes(wake);
        result
    }
}

/// Creates a signal and returns its read and write halves.
///
/// The signal is disposed when the current owner is cleaned up. Handles that
/// outlive it keep the value readable but notify nothing. With no current
/// owner nothing disposes it, and its entry in the runtime stays until the
/// thread ends.
///
/// ```
/// use smudge_core::reactive::{self, Owner, RenderEffect, prelude::*};
/// use std::cell::Cell;
/// use std::rc::Rc;
///
/// let owner = Owner::new();
/// owner.set();
/// let (count, set_count) = signal_local(3u32);
/// let seen = Rc::new(Cell::new(0u32));
/// let recorder = Rc::clone(&seen);
/// let _effect = RenderEffect::new(move || recorder.set(count.get()));
/// reactive::flush();
///
/// set_count.update(|value| *value += 1);
/// reactive::flush();
/// assert_eq!(seen.get(), 4);
/// ```
pub fn signal_local<T: 'static>(value: T) -> (ReadSignal<T>, WriteSignal<T>) {
    let node = runtime::with_runtime(runtime::Runtime::new_signal);
    let data = Rc::new(SignalData {
        value: RefCell::new(value),
        node: Cell::new(node),
    });
    (
        ReadSignal {
            data: Rc::clone(&data),
        },
        WriteSignal { data },
    )
}

/// A value computed from signals, recomputed when a read needs it.
///
/// A memo recomputes when it is read after one of its sources changed, and it
/// stops propagation when the new value compares equal to the old one, so
/// effects that read it do not rerun. Because a memo is always brought up to
/// date on read, a reader never sees a memo that disagrees with its sources.
///
/// The memo is disposed when the current owner is cleaned up. Handles that
/// outlive it keep the last value readable. With no current owner nothing
/// disposes it, so its computation stays in the runtime until the thread
/// ends. Cloning the handle is cheap, and every clone names the same memo.
pub struct Memo<T> {
    /// The value and the node that carries the subscribers.
    data: Rc<MemoData<T>>,
}

impl<T: 'static> Memo<T> {
    /// Creates a memo that computes its value with `compute`.
    ///
    /// The first computation runs at once, tracking the signals it reads into
    /// the effect or memo that is running, if any.
    ///
    /// The value type needs [`PartialEq`] so the memo can recognize an
    /// unchanged value and stop propagation.
    pub fn new(compute: impl Fn() -> T + 'static) -> Memo<T>
    where
        T: PartialEq,
    {
        let data = Rc::new(MemoData {
            value: RefCell::new(None),
            node: Cell::new(NodeId::default()),
        });
        let stored = Rc::clone(&data);
        let run: Rc<dyn Fn()> = Rc::new(move || {
            let value = compute();
            let changed = stored
                .value
                .borrow()
                .as_ref()
                .is_none_or(|old| *old != value);
            if changed {
                *stored.value.borrow_mut() = Some(value);
                let wake = runtime::with_runtime(|runtime| runtime.notify(stored.node.get()));
                runtime::fire_wakes(wake);
            }
        });
        let node = runtime::with_runtime(|runtime| runtime.new_memo(run));
        data.node.set(node);
        runtime::compute_new_memo(node);
        Memo { data }
    }
}

impl<T: 'static> With<T> for Memo<T> {
    fn with<U>(&self, fun: impl FnOnce(&T) -> U) -> U {
        runtime::update_memo(self.data.node.get());
        runtime::track_read(self.data.node.get());
        let value = self.data.value.borrow();
        fun(value.as_ref().expect(
            "a memo holds a value once its first computation finished, so a \
             read sees one unless the memo reads itself",
        ))
    }
}

impl<T: 'static> Read<T> for Memo<T> {
    fn read<U>(&self, fun: impl FnOnce(&T) -> U) -> U {
        runtime::update_memo(self.data.node.get());
        let value = self.data.value.borrow();
        fun(value.as_ref().expect(
            "a memo holds a value once its first computation finished, so a \
             read sees one unless the memo reads itself",
        ))
    }
}

/// A function that reruns when a signal or memo it read changes.
///
/// The first run happens when the effect is created, with tracking, so the
/// sources it reaches are the ones that wake it later. Every run re-tracks
/// from scratch, which makes conditional reads work.
///
/// The effect is owned by the current owner: cleaning that owner up, or
/// dropping its last handle, stops the effect and frees its closure. Created
/// with no current owner, the effect lives until the returned handle drops.
/// Dropping the handle of an owned effect does nothing.
///
/// A write inside an effect body queues the effect again, and a body that
/// keeps waking itself is stopped at a fixed number of runs per flush:
/// debug builds panic, release builds skip the effect for the rest of that
/// flush.
pub struct RenderEffect {
    /// The node that carries the sources, the queue state and the body.
    node: NodeId,
    /// Whether an owner took responsibility for disposing the node.
    owned: bool,
}

impl RenderEffect {
    /// Creates an effect and runs its body once, with tracking.
    ///
    /// The effect is owned by the current owner, when there is one. See the
    /// type's documentation for the lifetime rules. The body's return value
    /// is ignored.
    pub fn new<T>(mut run: impl FnMut() -> T + 'static) -> RenderEffect {
        let owned = runtime::with_runtime(|runtime| runtime.current_owner().is_some());
        let scope = runtime::with_runtime(|runtime| runtime.current_scope());
        let cell = Rc::new(EffectCell {
            run: RefCell::new(Some(Box::new(move || {
                run();
            }))),
        });
        let node = runtime::with_runtime(|runtime| runtime.new_effect(Rc::clone(&cell), scope));
        let mut guard = runtime::DisposeOnUnwind {
            node,
            armed: !owned,
        };
        runtime::run_body(&cell, node);
        guard.armed = false;
        RenderEffect { node, owned }
    }
}

impl Drop for RenderEffect {
    fn drop(&mut self) {
        if !self.owned {
            runtime::dispose(self.node);
        }
    }
}

/// The owner of the reactive values and effects created while it is current.
///
/// Owners form a tree. [`Owner::new`] attaches to the current owner when there
/// is one, [`Owner::child`] attaches to an owner directly, and [`Owner::set`]
/// and [`Owner::with`] make one current, which is where new values and effects
/// are registered. [`Owner::cleanup`] stops the owner's effects and disposes
/// its values, children first; dropping the last handle to an owner does the
/// same, so nothing has to be cleaned up by hand.
///
/// Context values are provided on an owner with [`provide_context`] and read
/// by the owner and its descendants with [`use_context`].
#[derive(Clone)]
pub struct Owner {
    /// The parent, scope and contents of the owner.
    inner: Rc<OwnerData>,
}

impl Default for Owner {
    fn default() -> Owner {
        Owner::new()
    }
}

impl Owner {
    /// Creates an owner under the current owner, when there is one.
    ///
    /// With no current owner the new owner starts a new root scope, which
    /// carries its own wake callback.
    pub fn new() -> Owner {
        let parent = runtime::with_runtime(|runtime| runtime.current_owner());
        let scope = runtime::with_runtime(|runtime| runtime.owner_scope(parent.as_deref()));
        let inner = Rc::new(OwnerData {
            parent: parent.as_ref().map(Rc::downgrade),
            scope,
            cleaned: Cell::new(false),
            state: RefCell::new(OwnerState::default()),
            timer_book: RefCell::new(None),
            clipboard: RefCell::new(None),
        });
        if let Some(parent) = parent {
            parent.adopt(&inner);
        }
        Owner { inner }
    }

    /// Creates an owner under this one.
    ///
    /// The child inherits this owner's root scope, so its effects wake the
    /// same redraw requests.
    pub fn child(&self) -> Owner {
        self.inner.child()
    }

    /// Makes this owner current until another one is set or a `with` block
    /// restores the previous one.
    pub fn set(&self) {
        runtime::with_runtime(|runtime| runtime.set_current(&self.inner));
    }

    /// Runs `fun` with this owner current, restoring the previous one after.
    pub fn with<T>(&self, fun: impl FnOnce() -> T) -> T {
        let _guard = CurrentOwnerGuard::enter(&self.inner);
        fun()
    }

    /// Stops the owner's effects and disposes the values created under it,
    /// children first, then runs the cleanup functions that
    /// [`Owner::on_cleanup`] registered.
    ///
    /// Running it twice does nothing. Dropping the last handle to the owner
    /// runs it too.
    pub fn cleanup(&self) {
        self.inner.cleanup();
    }

    /// Sets the callback that a wake in this owner's tree runs to request a
    /// redraw.
    ///
    /// Every effect created under this owner reports its wake here, so two
    /// owners on one thread each get their own redraw requests. See
    /// [`set_wake_callback`] for when the callback runs.
    pub fn set_wake_callback(&self, callback: impl Fn() + 'static) {
        self.inner.scope.wake.replace(Some(Rc::new(callback)));
    }

    /// Registers `fun` to run when the current owner is cleaned up.
    ///
    /// With no current owner, `fun` is dropped.
    pub fn on_cleanup(fun: impl FnOnce() + 'static) {
        let Some(owner) = Owner::current() else {
            return;
        };
        owner.state.borrow_mut().cleanups.push(Box::new(fun));
    }

    /// Returns the current owner, when one is set and still alive.
    fn current() -> Option<Rc<OwnerData>> {
        runtime::with_runtime(|runtime| runtime.current_owner())
    }

    /// Runs the wake callback of this owner's tree, when one is set.
    ///
    /// The callback runs outside the runtime, so it may write signals.
    pub(crate) fn wake(&self) {
        let callback = self.inner.scope.wake.borrow().clone();
        if let Some(callback) = callback {
            callback();
        }
    }

    /// Returns the owner's data, for the crate's own wiring such as the
    /// timer book an app installs on its root owner.
    pub(crate) fn data(&self) -> &Rc<OwnerData> {
        &self.inner
    }
}

impl Drop for Owner {
    fn drop(&mut self) {
        if Rc::strong_count(&self.inner) == 1 {
            self.inner.cleanup();
        }
    }
}

/// Stores `value` on the current owner for [`use_context`] to read.
///
/// The value is visible to the owner it was provided on and to everything
/// created under it, and invisible to its siblings and ancestors. A second
/// value of the same type replaces the first.
///
/// With no current owner, `value` is dropped.
pub fn provide_context<T: 'static>(value: T) {
    let Some(owner) = Owner::current() else {
        return;
    };
    let key = TypeId::of::<T>();
    let value: Rc<dyn std::any::Any> = Rc::new(value);
    let mut state = owner.state.borrow_mut();
    match state
        .contexts
        .iter_mut()
        .find(|(existing, _)| *existing == key)
    {
        Some((_, slot)) => *slot = value,
        None => state.contexts.push((key, value)),
    }
}

/// Returns a clone of the context value of type `T`, provided on the current
/// owner or the closest ancestor that provided one.
///
/// Returns `None` when neither has one.
pub fn use_context<T: Clone + 'static>() -> Option<T> {
    let key = TypeId::of::<T>();
    let mut current = Owner::current();
    while let Some(owner) = current {
        let found = owner
            .state
            .borrow()
            .contexts
            .iter()
            .find(|(existing, _)| *existing == key)
            .map(|(_, value)| Rc::clone(value));
        if let Some(value) = found
            && let Ok(value) = value.downcast::<T>()
        {
            return Some(T::clone(&value));
        }
        current = owner.parent.as_ref().and_then(Weak::upgrade);
    }
    None
}