Add non-blocking TryBeginInvoke and clarify the realtime threading model#13
Merged
Merged
Conversation
Adds the realtime-oriented invoker work from the .NET VST3 effects host plan (upstream roadmap item #4): - TryBeginInvoke(Action): a non-blocking, allocation-free, fire-and-forget path that marshals work onto the owner thread. Backed by a new bounded, lock-free multi-producer queue (Dmitry Vyukov's bounded MPMC algorithm) so producers neither block nor allocate; returns false when the bounded queue is full instead of growing unboundedly. Drained in FIFO order by DoInvokes alongside the existing Task queue. Runs immediately when called on the owner thread. - New Invoker(int beginInvokeCapacity) constructor to size the queue. - XML-doc clarification that Invoker is owner-thread-oriented and that the blocking/async paths (which allocate a Task and may block) must never be called from a hard real-time audio thread; audio->UI telemetry should use a dedicated SPSC ring buffer instead. Includes MSTest coverage: immediate owner-thread execution, cross-thread queueing, FIFO ordering, full-queue rejection, and a concurrent multi-producer delivery test.
CI's code-style analyzers (which the local sandbox SDK cannot load) flag the explicit capacity constructor as IDE0290. Convert to a primary constructor taking beginInvokeCapacity, with the parameterless constructor delegating to it via the default capacity. Behaviour is unchanged.
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
Implements upstream roadmap item #4 from the .NET VST3 effects host plan: clarify Invoker's realtime story and add a non-blocking, allocation-free marshalling path for non-realtime producers.
TryBeginInvoke(Action)A fire-and-forget counterpart to
Invoke/InvokeAsync:Taskis created and the caller never blocks waiting for the owner thread to pump.falsewhen the bounded queue is full (the action is dropped) rather than growing unboundedly — predictable memory behaviour.DoInvokes, alongside the existingTaskqueue.Invoker(int beginInvokeCapacity)constructor sizes the queue (default 1024).BoundedMpscQueue<T>(internal)A bounded, lock-free queue implementing Dmitry Vyukov's bounded MPMC algorithm (per-cell sequence numbers, single CAS per op). Safe for any number of concurrent producers; pre-allocates its cells and allocates nothing per enqueue/dequeue.
Documentation
Adds an XML-doc threading section making explicit that:
Taskand may block, so they must never be called from a hard real-time audio thread. Audio→UI telemetry should flow through a dedicated SPSC ring buffer (see the companion Containers PR) rather than the invoker.Testing
Added
TryBeginInvokeTests: null-guard, immediate owner-thread execution, cross-thread queue-until-pump, FIFO ordering, full-queue rejection, and a 4-producer × 10k concurrent delivery test. Full suite: 16/16 passing locally (net10.0).🤖 Part of the ktsu VST plugin upstream-enablement work.
https://claude.ai/code/session_01JQ3bQMuSYuumAnQZaYUKP7
Generated by Claude Code