namespace AcDream.App.Rendering; /// /// Single logical admission gate for callbacks entering the application host. /// Physical event removal remains important for ownership, but closing this /// gate first makes a still-attached native callback inert while teardown /// converges. /// internal sealed class HostQuiescenceGate { private readonly object _sync = new(); private bool _accepting = true; public bool IsAccepting { get { lock (_sync) return _accepting; } } internal bool IsEnteredByCurrentThread => Monitor.IsEntered(_sync); /// /// Closes admission after any callback already executing on another /// thread has returned. Monitor reentrancy lets the native Closing /// callback close its own gate without waiting on itself. /// public void StopAccepting() { lock (_sync) _accepting = false; } public void Invoke(Action callback) { ArgumentNullException.ThrowIfNull(callback); lock (_sync) { if (_accepting) callback(); } } public void Invoke(Action callback, T value) { ArgumentNullException.ThrowIfNull(callback); lock (_sync) { if (_accepting) callback(value); } } }