using System; using System.Threading; namespace MediaBrowser.Common.Configuration { /// /// Marks the flow of control that is applying an invalidation published by another instance, so the /// reactions to it can tell a remote write apart from a local one. /// /// /// Applying an invalidation raises the same update events a local save raises, because the in-process /// consumers have to re-read the configuration either way. Some of those consumers answer an update by /// writing, and that write must neither repeat what the publishing instance already did nor fan back /// out over the bus. The flag rides the execution context, so it reaches the queued and asynchronous /// event handlers as well as the synchronous ones. /// public static class ConfigurationInvalidationContext { private static readonly AsyncLocal _applyingRemoteInvalidation = new(); /// /// Gets a value indicating whether the current flow of control is applying an invalidation /// published by another instance rather than handling a local save. /// public static bool IsApplyingRemoteInvalidation => _applyingRemoteInvalidation.Value; /// /// Marks the current flow of control as applying a remote invalidation until the returned scope is /// disposed. /// /// The scope to dispose once the invalidation has been applied. public static IDisposable BeginApply() => new ApplyScope(); private sealed class ApplyScope : IDisposable { private readonly bool _previous; private bool _disposed; public ApplyScope() { _previous = _applyingRemoteInvalidation.Value; _applyingRemoteInvalidation.Value = true; } public void Dispose() { if (_disposed) { return; } _disposed = true; _applyingRemoteInvalidation.Value = _previous; } } } }