Files
ShrinkEventBus/Runtime/ShrinkEventBusRuntime.cs
T

85 lines
2.7 KiB
C#

#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
}