using System;
using System.Collections.Generic;
using System.Threading;
using JetBrains.Collections.Viewable;
using JetBrains.Diagnostics;
using UnityEditor;
namespace JetBrains.Rider.Unity.Editor
{
internal class MainThreadDispatcher : IScheduler
{
private static Thread ourUIThread;
internal static readonly MainThreadDispatcher Instance = new MainThreadDispatcher();
///
/// The queue of tasks that are being requested for the next time DispatchTasks is called
///
private readonly Queue myTaskQueue = new Queue();
private MainThreadDispatcher()
{
PluginEntryPoint.AppDomainLifetime.Bracket(() => EditorApplication.update += DispatchTasks,
() => EditorApplication.update -= DispatchTasks);
}
///
/// Dispatches the specified action delegate.
///
/// Action being requested
public void Queue(Action action)
{
if (Thread.CurrentThread == ourUIThread)
{
action();
return;
}
lock (myTaskQueue)
{
myTaskQueue.Enqueue(action);
}
}
///
/// Dispatches the tasks that has been requested since the last call to this function
///
private void DispatchTasks()
{
ourUIThread = Thread.CurrentThread;
if (myTaskQueue.Count == 0)
return;
while (true)
{
try
{
if (myTaskQueue.Count == 0)
return;
var task = myTaskQueue.Dequeue();
task();
}
catch (Exception e)
{
Log.GetLog().Error(e);
}
}
}
public static void AssertThread()
{
Assertion.Require(ourUIThread == null || ourUIThread == Thread.CurrentThread, "Not a UI thread");
}
///
/// Indicates whether there are tasks available for dispatching
///
///
/// true if there are tasks available for dispatching; otherwise, false.
///
public bool IsActive => ourUIThread == null || ourUIThread == Thread.CurrentThread;
public bool OutOfOrderExecution => false;
}
}