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
//! Background solving for the "Edit" sub-tab: moves `Design::solve` off the UI thread
//! for the explicit "Solve" action (button and F5, via [`super::view::refresh_all`]'s
//! large-design path) and, when the design is cheap enough, schedules the SAME
//! machinery automatically after an edit ("auto-solve") so small/medium designs get a
//! fresh path-traced view and masts without a click. See `mod.rs`'s "Never block the
//! UI thread with a solve" section for the rule this exists to uphold.
//!
//! # Why a `thread_local!`, not a new `EditorState` field
//!
//! `deep_solve`/`optimize`'s in-flight handles live directly on `EditorState`
//! (`state/mod.rs`), which is NOT this group's file to edit. Everything this module
//! needs beyond `EditorState::design`/`generation` (both already readable through a
//! plain `&EditorState`) -- the debounce timer, the running request counter, the last
//! measured solve time, and the shared solid-preview handles a completed background
//! solve pushes into -- lives instead in [`runtime::Runtime`], a `thread_local!`
//! singleton. That is sound for the identical reason `EditorState` itself gets away
//! with a plain `Rc<RefCell<..>>` rather than `Arc<Mutex<..>>` (see that struct's own
//! doc comment): every function in this group that touches `Runtime` runs on the
//! UI/event-loop thread, either directly from a Slint callback or from inside a
//! `Weak::upgrade_in_event_loop` closure. The worker threads this group spawns never
//! touch `Runtime` themselves -- they only compute pure `Design` -> data conversions
//! and hand the result back across the event-loop boundary.
//!
//! # Two kinds of "stale" a completed background solve must detect
//!
//! A background solve is dispatched against a snapshot: a cloned [`Design`] plus the
//! [`EditorState::generation`] counter's value at that moment. By the time it
//! completes, either or both of the following can have happened, and
//! [`apply::apply_background_solve_result`] must not let either corrupt the
//! display:
//!
//! 1. **A newer background solve was dispatched** (the user clicked Solve again, or
//! another auto-solve fired) before this one returned. [`runtime::Runtime::current_seq`]
//! is bumped on every dispatch; a completion only touches the UI at all while its
//! own sequence number still matches -- an older one simply has nothing left to
//! do, since the newer dispatch already owns the "Solving..." banner and will
//! apply its own result in turn.
//! 2. **The design changed without a new dispatch** -- possible when auto-solve is
//! disabled (or this design's own measured cost exceeds the budget) and an edit
//! lands while an explicit Solve from BEFORE that edit is still running. Here this
//! result's own sequence number is still current (nothing superseded it), but
//! `generation` has moved past what was captured at dispatch time. The edit's own
//! [`super::view::refresh_editor_panel_stale`] call already repainted the banner
//! correctly at edit time, so this arm only needs to clear `editor_solve_running`
//! (nothing else will) and otherwise touch nothing.
//!
//! Both checks are cheap `u64` comparisons; nothing here ever tries to reinterpret a
//! stale result's tier indices against a design it no longer describes.
//!
//! # Layout of this group
//!
//! [`runtime`] holds the `thread_local!` state and the handles [`init`] stashes into
//! it. [`scheduling`] decides whether/when a solve should run synchronously or be
//! debounced into an auto-solve. [`dispatch`] spawns the background solve and ticks
//! its banner; [`apply`] applies the completed result back onto the UI. [`replan`]
//! is the solid-preview replan handshake: converting an already-solved mast list to
//! viewport planes, stashing the design snapshot a matching preview frame consumes,
//! and the idle-replan follow-up for a partial frame. [`tests`] covers all five.
pub use ;
pub use ;
pub use ;
pub use ;