docs: demonstrate collection of mounted cycles with suspended workflows
This commit is contained in:
@@ -549,7 +549,9 @@ Source paint now uses a resumable read-only VM call with the same 256-instructio
|
||||
Layout and paint drivers now prepare one occurrence at a time. Their fixed-size outer bytecode repeats on the same VM frame; a short-lived helper retains only the current call, its bounds/arguments and collector. The helper is released before the next occurrence. Layout keeps bottom-up measure, top-down arrange and the same settling loop. Paint advances even intrinsic method classification through VM quanta. The weak occurrence list and native scratch/output data remain proportional to the actual tree, but preparation no longer allocates managed callables/Bounds for the whole tree before the first slice. All helpers share the original read-only scope and cumulative instruction/frame limits. Weak-list copying, structural extraction, settling and final projection remain bounded atomic native work.
|
||||
|
||||
|
||||
ui.stats().dependencyInvalidations counts observed layout/paint dependency mismatches. lastInvalidDependency records the phase, object kind/identity and old/current versions without rendering its fields or retaining it. An input changing its globals is an expected invalidation; compare idle document versions before diagnosing a refresh loop.
|
||||
ui.stats().dependencyInvalidations counts observed layout/paint dependency mismatches. lastInvalidDependency records the phase and invalidating identity/name or snapshot-cache cause without rendering its fields or retaining it. windowDependencyDiagnostics reports nonempty reasons from all windows. Source rendering observes the global names it reads, so unrelated global changes do not require repainting; compare idle document versions before diagnosing a refresh loop.
|
||||
|
||||
examples/gc-lifecycle.endor demonstrates an actual Page/Block/Task/await-frame reference cycle. Record ui.stats().objects, call mountCycle(), and inspect phase.value (1 while awaiting) and pending.value.status(). Closing the tab removes its navigation root; a retained Block's own workflow continues. Call releaseCycle() to release both external references, then query objects again to trigger the normal between-input collection and compare with the same baseline. Cached layout/paint metadata borrows identities and must not keep that cycle alive. The baseline is specific to that VM/program, not a fixed object count across programs.
|
||||
|
||||
|
||||
ui.readText(owner,key,path[,callback]) returns an owner-scoped Task and reads a regular UTF-8 file off the VM thread. Paths use native filesystem syntax; absolute paths are recommended. The optional callback takes zero arguments and must return Unit; it runs only on successful read and can use task.result(). Without a callback, poll status then read result from code. result() is available while a success callback is running or after completion (timers return Unit); error() returns an empty String until failed, then the provider/callback error. A provider failure marks the task failed and skips its callback without stopping the VM; a source callback failure still stops the shared domain. Owner/key replacement, explicit cancellation, close/reset/VM discard and GC drop the provider lease, remove queued completion and reject late delivery. In-progress OS reads may finish, but cannot deliver after cancellation. Only the owning VM worker updates managed results and rechecks owner/key identity. No VM handles enter provider threads beyond opaque weak identities.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
| File | Purpose |
|
||||
| --- | --- |
|
||||
| [gc-lifecycle.endor](gc-lifecycle.endor) | A Page/Block/Task/await-frame cycle: hidden retained Blocks keep running, then releasing the last references permits collection despite rendering caches. |
|
||||
| [scroll-axis.endor](scroll-axis.endor) | One shared TextBlock in vertical and horizontal viewports, live axis changes and independent offsets. |
|
||||
| [windows.endor](windows.endor) | Two real native windows in one Aster VM, live shared counter state and explicit Page ownership. |
|
||||
| [tabs.endor](tabs.endor) | Three real Page tabs, shared counter state, source titles, native switching/closing and reopening through code. |
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// Record ui.stats().objects, call mountCycle(), then inspect phase.value and
|
||||
// pending.value.status(). Close the tab: the referenced Block still waits.
|
||||
// releaseCycle() removes both external references; the next objects query
|
||||
// should return to the same baseline before the five-minute wait finishes.
|
||||
holder = ui.state(0)
|
||||
pending = ui.state(0)
|
||||
phase = ui.state(0)
|
||||
class CycleRect: RectBlock {
|
||||
peer: Object
|
||||
function wait(self: CycleRect): Unit {
|
||||
gate = ui.sleep(self,"sleep",300000)
|
||||
phase.set(1)
|
||||
done = await gate
|
||||
phase.set(2)
|
||||
self.peer.title = "等待已结束"
|
||||
}
|
||||
function measure(self: CycleRect, mount: Mount, constraints: Constraints): MeasureResult {
|
||||
observed = self.peer.title
|
||||
return MeasureResult(180,40)
|
||||
}
|
||||
function paint(self: CycleRect, mount: Mount, geometry: Bounds): DisplayList {
|
||||
observed = self.peer.title
|
||||
return RectBlock.paint(self,mount,geometry)
|
||||
}
|
||||
}
|
||||
function mountCycle(): Unit {
|
||||
transient = Page()
|
||||
transient.title = "临时引用环"
|
||||
rect = CycleRect(180,40,8,"#3868D9",transient)
|
||||
transient.render(rect)
|
||||
holder.set(transient)
|
||||
phase.set(0)
|
||||
pending.set(ui.spawn(rect,"workflow",rect.wait))
|
||||
}
|
||||
function releaseCycle(): Unit {
|
||||
holder.value.close()
|
||||
holder.set(0)
|
||||
pending.set(0)
|
||||
}
|
||||
base = Page()
|
||||
base.title = "GC 基线"
|
||||
base.render(TextBlock("关闭临时 Page 后应回收引用环",2))
|
||||
Reference in New Issue
Block a user