#nullable enable using System; using System.Threading; #if UNITY_5_3_OR_NEWER using MainThreadDispatcherContract = ShrinkEventBus.IShrinkEventBusMainThreadDispatcher; #else using MainThreadDispatcherContract = ShrinkSDK.Runtime.IShrinkMainThreadDispatcher; #endif namespace ShrinkEventBus { public static class ShrinkEventBusRuntime { private static MainThreadDispatcherContract _mainThreadDispatcher = CreateDefaultDispatcher(); public static MainThreadDispatcherContract MainThreadDispatcher => Volatile.Read(ref _mainThreadDispatcher); public static void ConfigureMainThreadDispatcher(MainThreadDispatcherContract dispatcher) { if (dispatcher == null) throw new ArgumentNullException(nameof(dispatcher)); Volatile.Write(ref _mainThreadDispatcher, dispatcher); } private static MainThreadDispatcherContract CreateDefaultDispatcher() { #if UNITY_5_3_OR_NEWER return new ShrinkUnityMainThreadDispatcher(); #else return new ShrinkSynchronizationContextDispatcher( SynchronizationContext.Current, Thread.CurrentThread.ManagedThreadId); #endif } } #if UNITY_5_3_OR_NEWER internal sealed class ShrinkUnityMainThreadDispatcher : MainThreadDispatcherContract { public bool IsMainThread => Cysharp.Threading.Tasks.PlayerLoopHelper.IsMainThread; public bool TryPost(Action action) { if (action == null) throw new ArgumentNullException(nameof(action)); Cysharp.Threading.Tasks.PlayerLoopHelper.AddContinuation( Cysharp.Threading.Tasks.PlayerLoopTiming.Update, action); return true; } } #else internal sealed class ShrinkSynchronizationContextDispatcher : MainThreadDispatcherContract { private readonly SynchronizationContext? _context; private readonly int _threadId; public ShrinkSynchronizationContextDispatcher(SynchronizationContext? context, int threadId) { _context = context; _threadId = threadId; } public bool IsMainThread => Thread.CurrentThread.ManagedThreadId == _threadId; public bool TryPost(Action action) { if (action == null) throw new ArgumentNullException(nameof(action)); if (IsMainThread) { action(); return true; } if (_context == null) return false; _context.Post(static state => ((Action)state!).Invoke(), action); return true; } } #endif }