using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; namespace Unity.CodeEditor.Utils { /// /// This class is used to prevent stack overflows by representing a 'busy' flag /// that prevents reentrance when another call is running. /// However, using a simple 'bool busy' is not thread-safe, so we use a /// thread-static BusyManager. /// internal static class BusyManager { [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")] [SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Justification = "Should always be used with 'var'")] internal struct BusyLock : IDisposable { internal static readonly BusyLock Failed = new BusyLock(null); private readonly List _objectList; internal BusyLock(List objectList) { _objectList = objectList; } internal bool Success => _objectList != null; public void Dispose() { _objectList?.RemoveAt(_objectList.Count - 1); } } [ThreadStatic] private static List _activeObjects; internal static BusyLock Enter(object obj) { var activeObjects = _activeObjects ?? (_activeObjects = new List()); if (activeObjects.Any(t => t == obj)) { return BusyLock.Failed; } activeObjects.Add(obj); return new BusyLock(activeObjects); } } }