209 lines
5.4 KiB
C#
209 lines
5.4 KiB
C#
|
namespace Dreamteck.Splines
|
||
|
{
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.SceneManagement;
|
||
|
#if !UNITY_WSA
|
||
|
using System.Threading;
|
||
|
#endif
|
||
|
|
||
|
public static class SplineThreading
|
||
|
{
|
||
|
public delegate void EmptyHandler();
|
||
|
public static int threadCount
|
||
|
{
|
||
|
get {
|
||
|
#if UNITY_WSA
|
||
|
return 0;
|
||
|
#else
|
||
|
return threads.Length;
|
||
|
#endif
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
#if !UNITY_WSA
|
||
|
if(value > threads.Length)
|
||
|
{
|
||
|
while (threads.Length < value)
|
||
|
{
|
||
|
ThreadDef thread = new ThreadDef();
|
||
|
#if UNITY_EDITOR
|
||
|
if (Application.isPlaying)
|
||
|
{
|
||
|
thread.Restart();
|
||
|
}
|
||
|
#else
|
||
|
thread.Restart();
|
||
|
#endif
|
||
|
ArrayUtility.Add(ref threads, thread);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
#if !UNITY_WSA
|
||
|
internal class ThreadDef
|
||
|
{
|
||
|
internal class Worker
|
||
|
{
|
||
|
internal bool computing = false;
|
||
|
internal Queue<EmptyHandler> instructions = new Queue<EmptyHandler>();
|
||
|
}
|
||
|
internal delegate void BoolHandler(bool flag);
|
||
|
private ParameterizedThreadStart start = null;
|
||
|
internal Thread thread = null;
|
||
|
private Worker worker = new Worker();
|
||
|
internal bool isAlive
|
||
|
{
|
||
|
get { return thread != null && thread.IsAlive; }
|
||
|
}
|
||
|
internal bool computing
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return worker.computing;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal ThreadDef()
|
||
|
{
|
||
|
start = new ParameterizedThreadStart(RunThread);
|
||
|
}
|
||
|
|
||
|
internal void Queue(EmptyHandler handler)
|
||
|
{
|
||
|
worker.instructions.Enqueue(handler);
|
||
|
}
|
||
|
|
||
|
internal void Interrupt()
|
||
|
{
|
||
|
thread.Interrupt();
|
||
|
}
|
||
|
|
||
|
internal void Restart()
|
||
|
{
|
||
|
thread = new Thread(start);
|
||
|
thread.Start(worker);
|
||
|
}
|
||
|
|
||
|
internal void Abort()
|
||
|
{
|
||
|
if (isAlive)
|
||
|
{
|
||
|
thread.Abort();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
internal static ThreadDef[] threads = new ThreadDef[2];
|
||
|
internal static readonly object locker = new object();
|
||
|
static SplineThreading()
|
||
|
{
|
||
|
Application.quitting += Quitting;
|
||
|
for (int i = 0; i < threads.Length; i++)
|
||
|
{
|
||
|
threads[i] = new ThreadDef();
|
||
|
}
|
||
|
|
||
|
#if UNITY_EDITOR
|
||
|
PrewarmThreads();
|
||
|
UnityEditor.EditorApplication.playModeStateChanged += OnPlayStateChanged;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#if UNITY_EDITOR
|
||
|
static void OnPlayStateChanged(UnityEditor.PlayModeStateChange state)
|
||
|
{
|
||
|
if (state == UnityEditor.PlayModeStateChange.ExitingPlayMode)
|
||
|
{
|
||
|
Quitting();
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static void Quitting()
|
||
|
{
|
||
|
Stop();
|
||
|
}
|
||
|
|
||
|
static void RunThread(object o)
|
||
|
{
|
||
|
ThreadDef.Worker work = (ThreadDef.Worker)o;
|
||
|
while (true)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
work.computing = false;
|
||
|
Thread.Sleep(Timeout.Infinite);
|
||
|
}
|
||
|
catch (ThreadInterruptedException)
|
||
|
{
|
||
|
work.computing = true;
|
||
|
lock (locker)
|
||
|
{
|
||
|
while (work.instructions.Count > 0)
|
||
|
{
|
||
|
EmptyHandler h = work.instructions.Dequeue();
|
||
|
if (h != null) h();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
catch (System.Exception ex)
|
||
|
{
|
||
|
if(ex.Message != "") Debug.LogError("THREAD EXCEPTION " + ex.Message);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
Debug.Log("Thread stopped");
|
||
|
work.computing = false;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
public static void Run(EmptyHandler handler)
|
||
|
{
|
||
|
#if !UNITY_WSA
|
||
|
#if UNITY_EDITOR
|
||
|
if (!Application.isPlaying)
|
||
|
{
|
||
|
handler();
|
||
|
return;
|
||
|
}
|
||
|
#endif
|
||
|
for (int i = 0; i < threads.Length; i++)
|
||
|
{
|
||
|
if (!threads[i].isAlive) threads[i].Restart();
|
||
|
if (!threads[i].computing || i == threads.Length - 1)
|
||
|
{
|
||
|
threads[i].Queue(handler);
|
||
|
if(!threads[i].computing)threads[i].Interrupt();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
public static void PrewarmThreads()
|
||
|
{
|
||
|
#if !UNITY_WSA
|
||
|
for (int i = 0; i < threads.Length; i++)
|
||
|
{
|
||
|
if (!threads[i].isAlive)
|
||
|
{
|
||
|
threads[i].Restart();
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
public static void Stop()
|
||
|
{
|
||
|
#if !UNITY_WSA
|
||
|
for (int i = 0; i < threads.Length; i++)
|
||
|
{
|
||
|
threads[i].Abort();
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
}
|