/****************************************************************************
* Copyright 2019 Nreal Techonology Limited. All rights reserved.
*
* This file is part of NRSDK.
*
* https://www.nreal.ai/
*
*****************************************************************************/
namespace NRKernal
{
using System;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
/// A main thread dispather.
[ExecuteInEditMode]
public class MainThreadDispather : MonoBehaviour
{
/// A delayed queue item.
public class DelayedQueueItem
{
/// The time.
public float time;
/// The action.
public Action action;
}
/// The current.
private static MainThreadDispather m_Current;
/// Number of.
private int m_Count;
/// Current time.
private static float m_CurrentTime;
/// True once initialization is complete.
private static bool m_Initialized;
/// Identifier for the thread.
private static int m_ThreadId = -1;
/// The actions.
private List m_Actions = new List();
/// The delayed.
private List m_Delayed = new List();
/// Gets the current.
/// The current.
public static MainThreadDispather Current
{
get
{
if (!MainThreadDispather.m_Initialized)
{
MainThreadDispather.Initialize();
}
return MainThreadDispather.m_Current;
}
}
/// Initializes this object.
public static void Initialize()
{
bool flag = !MainThreadDispather.m_Initialized;
if (flag && MainThreadDispather.m_ThreadId != -1 && MainThreadDispather.m_ThreadId != Thread.CurrentThread.ManagedThreadId)
{
return;
}
if (flag)
{
GameObject gameObject = new GameObject("MainThreadDispather");
gameObject.hideFlags = HideFlags.DontSave;
UnityEngine.Object.DontDestroyOnLoad(gameObject);
if (MainThreadDispather.m_Current)
{
if (Application.isPlaying)
{
UnityEngine.Object.Destroy(MainThreadDispather.m_Current.gameObject);
}
else
{
UnityEngine.Object.DestroyImmediate(MainThreadDispather.m_Current.gameObject);
}
}
MainThreadDispather.m_Current = gameObject.AddComponent();
UnityEngine.Object.DontDestroyOnLoad(MainThreadDispather.m_Current);
MainThreadDispather.m_Initialized = true;
MainThreadDispather.m_ThreadId = Thread.CurrentThread.ManagedThreadId;
MainThreadDispather.m_CurrentTime = Time.time;
}
}
/// Executes the 'destroy' action.
private void OnDestroy()
{
MainThreadDispather.m_Initialized = false;
}
/// Queue on main thread.
/// The action.
public static void QueueOnMainThread(Action action)
{
MainThreadDispather.QueueOnMainThread(action, 0f);
}
/// Queue on main thread.
/// The action.
/// The time.
public static void QueueOnMainThread(Action action, float time)
{
if (time != 0f)
{
List delayed = MainThreadDispather.Current.m_Delayed;
lock (delayed)
{
MainThreadDispather.Current.m_Delayed.Add(new MainThreadDispather.DelayedQueueItem
{
time = m_CurrentTime + time,
action = action
});
}
}
else
{
List actions = MainThreadDispather.Current.m_Actions;
lock (actions)
{
MainThreadDispather.Current.m_Actions.Add(action);
}
}
}
/// Executes the 'asynchronous' operation.
/// The action.
public static void RunAsync(Action action)
{
new Thread(new ParameterizedThreadStart(MainThreadDispather.RunAction))
{
Priority = System.Threading.ThreadPriority.Normal
}.Start(action);
}
/// Executes the action.
/// The action.
private static void RunAction(object action)
{
((Action)action)?.Invoke();
}
/// Updates this object.
private void Update()
{
MainThreadDispather.m_CurrentTime = Time.time;
List actions = this.m_Actions;
if (actions.Count > 0)
{
lock (actions)
{
for (int i = 0; i < this.m_Actions.Count; i++)
{
this.m_Actions[i]();
}
this.m_Actions.Clear();
}
}
List delayed = this.m_Delayed;
if (delayed.Count > 0)
{
lock (delayed)
{
for (int j = 0; j < this.m_Delayed.Count; j++)
{
MainThreadDispather.DelayedQueueItem delayedQueueItem = this.m_Delayed[j];
if (delayedQueueItem.time <= MainThreadDispather.m_CurrentTime)
{
delayedQueueItem.action();
this.m_Delayed.RemoveAt(j);
j--;
}
}
}
}
}
}
}