mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-04 05:58:12 +08:00
Serve the monitored lane from its own capture materialization
This commit is contained in:
@@ -192,34 +192,54 @@ fn monitor<'e>(
|
|||||||
#[data] io: MonitorValue,
|
#[data] io: MonitorValue,
|
||||||
content: impl Node<Context<'_>, Output = RecordValue<'e>>,
|
content: impl Node<Context<'_>, Output = RecordValue<'e>>,
|
||||||
) -> GPoll<RecordValue<'e>> {
|
) -> GPoll<RecordValue<'e>> {
|
||||||
let result = content.eval(&ctx);
|
let entry_sp = core_types::record::stack::sp();
|
||||||
// The capture covers the whole extent, so it runs on the first lane only:
|
let publish = |captured: Option<RecordCapture>| {
|
||||||
// running it per lane would re-materialize the level per lane and compound
|
|
||||||
// through nested monitors.
|
|
||||||
if ctx.innermost_index() == 0
|
|
||||||
&& let GPoll::Final(value) | GPoll::Partial(value) = &result
|
|
||||||
{
|
|
||||||
// The materialization below evaluates the level again; its frames sit
|
|
||||||
// above the one this eval already claimed and must not survive.
|
|
||||||
let mark = core_types::record::stack::sp();
|
|
||||||
let captured = match content.layout().depth {
|
|
||||||
// SAFETY: the value came from this edge, so it carries the edge's layout.
|
|
||||||
0 => unsafe { RecordCapture::capture(content.layout(), content.layout().rec(value), ctx.arena()) },
|
|
||||||
// A leveled wire captures its whole extent, not the one lane this
|
|
||||||
// context addresses.
|
|
||||||
_ => match content.materialize_level(ctx, ctx.arena()) {
|
|
||||||
// SAFETY: the batch came from this edge, so it carries the edge's layout.
|
|
||||||
LevelStatus::Batch(batch, _) => unsafe { RecordCapture::capture_level(content.layout(), batch, ctx.arena()) },
|
|
||||||
LevelStatus::Pending | LevelStatus::Error(_) => None,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
// SAFETY: the capture copies into the arena, so nothing borrows the
|
|
||||||
// frames left above the mark.
|
|
||||||
unsafe { core_types::record::stack::rewind(mark) };
|
|
||||||
*io.lock().unwrap() = captured.map(|output| IORecord {
|
*io.lock().unwrap() = captured.map(|output| IORecord {
|
||||||
input: CtxSnapshot::capture(ctx),
|
input: CtxSnapshot::capture(ctx),
|
||||||
output,
|
output,
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
// A leveled capture covers the whole extent, which the materialization below
|
||||||
|
// computes lane by lane. Serving THIS lane out of that batch rather than
|
||||||
|
// evaluating the content separately is what keeps the cost linear: the extra
|
||||||
|
// eval would double the work under every enclosing monitor.
|
||||||
|
if content.layout().depth > 0 && ctx.innermost_index() == 0 {
|
||||||
|
return match content.materialize_level(ctx, ctx.arena()) {
|
||||||
|
LevelStatus::Batch(batch, finality) => {
|
||||||
|
// SAFETY: the batch came from this edge, so it carries the edge's layout.
|
||||||
|
publish(unsafe { RecordCapture::capture_level(content.layout(), batch, ctx.arena()) });
|
||||||
|
let Some(lane) = (!batch.is_empty()).then(|| batch.get(0)) else {
|
||||||
|
// An empty level ends here; the past-end signal serves drains.
|
||||||
|
claim_frame(content.layout());
|
||||||
|
return GPoll::Error(Box::new(core_types::gpoll::GraphError::past_end()));
|
||||||
|
};
|
||||||
|
// SAFETY: the lane is a live record of this edge's layout.
|
||||||
|
let value = unsafe { serve_frame(content.layout(), lane.rec().ptr()) };
|
||||||
|
match finality {
|
||||||
|
Finality::AllFinal => GPoll::Final(value),
|
||||||
|
Finality::Partial => GPoll::Partial(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// A valueless materialization leaves frames no one reads, so the
|
||||||
|
// entry mark, not the current top, is what this node's frame sits on.
|
||||||
|
LevelStatus::Pending => {
|
||||||
|
// SAFETY: nothing borrows the frames above the entry mark.
|
||||||
|
unsafe { core_types::record::interrupt_frame(entry_sp, content.layout()) };
|
||||||
|
GPoll::Pending
|
||||||
|
}
|
||||||
|
LevelStatus::Error(error) => {
|
||||||
|
// SAFETY: nothing borrows the frames above the entry mark.
|
||||||
|
unsafe { core_types::record::interrupt_frame(entry_sp, content.layout()) };
|
||||||
|
GPoll::Error(Box::new(error))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let result = content.eval(&ctx);
|
||||||
|
if ctx.innermost_index() == 0
|
||||||
|
&& let GPoll::Final(value) | GPoll::Partial(value) = &result
|
||||||
|
{
|
||||||
|
// SAFETY: the value came from this edge, so it carries the edge's layout.
|
||||||
|
publish(unsafe { RecordCapture::capture(content.layout(), content.layout().rec(value), ctx.arena()) });
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user