feat: add GraphContext, a graph-scoped side channel for stages - #9
Merged
Merged
Conversation
- GraphContext: type-keyed, thread-safe blackboard (set / get / getOr / contains / erase / update / clear); values are copied in and out under a shared_mutex, update() is atomic - polymorphic base: derive an application context and recover it with as<Derived>() - MessageFilter::setContext / context(): a graph hands its context to its stages once; FilterGraph, DslFilterGraph, JsonFilterGraph, AnyFilterChain, FanoutFilter and JoinFilter forward it, including to nested graphs and to receivers/paths added later - breaking: AnyMessageFilter::setContext is pure virtual - README section and CHANGELOG entries
psyinf
added this pull request to stack #12
September 17, 2026 17:44
This was referenced Sep 17, 2026
context() is never null: a stage starts with its own empty context, and every graph hands its context to its stages when it is built, not only on an explicit setContext. So stages of a graph share one context out of the box and no stage needs a null check. - MessageFilter: mContext is always set; setContext(nullptr) installs a fresh empty context; context() returns GraphContext& (const overload too) and sharedContext() the shared_ptr for composites to forward - FilterGraph, JsonFilterGraph, DslFilterGraph propagate their context from their constructor; AnyFilterChain owns one and does the same, so a chain built on its own has one context, not one per stage - FanoutFilter / JoinFilter hand sharedContext() to late receivers/paths - a graph overwrites the context of the stages it is built from, so a shared context goes to the graph, not to individual stages
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
GraphContext, a side channel that lets stages share data (e.g. a frame number) without changing the message type and without knowing which stage published it.GraphContext(GraphContext.hpp): one value per type, keyed by the type itself (set/get/getOr/contains/erase/update/clear). Values are copied in and out under ashared_mutex, andupdate()is atomic.GraphContextis a polymorphic base. An application can derive its own context and recover it withas<Derived>().MessageFilter::setContext/context(). The graph hands over the context once, andFilterGraph,DslFilterGraph,JsonFilterGraph,AnyFilterChain,FanoutFilterandJoinFilterforward it, including to nested graphs and to fanout receivers / join paths added later.Breaking change
AnyMessageFilter::setContextis pure virtual. CustomAnyMessageFilterimplementations must implement it and forward the context to the stages they wrap. It is pure rather than a no-op on purpose: a composite that forgot to forward would otherwise fail silently.Design notes
context()isnullptruntilsetContextis called, so stages must check it.setContextis meant to be called before processing, not concurrently withfilter().as<Derived>()couples a stage to that type, so reusable stages should useset/get.Testing
New
GraphContextTests: store semantics, copy-out, erase/clear, atomicupdateacross 8 threads, derived contexts, a stage without a context, and propagation throughFilterGraph,DslFilterGraph, and fanout/join paths nested in aJsonFilterGraph. The full suite passes locally (68/68, MSVC debug with ASan).