diff --git a/Scripts/Format/VRMImporter.cs b/Scripts/Format/VRMImporter.cs index be9a70ae97..38894249b2 100644 --- a/Scripts/Format/VRMImporter.cs +++ b/Scripts/Format/VRMImporter.cs @@ -564,7 +564,7 @@ public static void LoadVrmAsync(VRMImporterContext ctx, ArraySegment chunk var schedulable = Schedulable.Create(); schedulable - .AddTask(MainThreadDispatcher.Instance.ThreadScheduler, () => + .AddTask(Scheduler.ThreadPool, () => { ctx.GLTF.baseDir = Path.GetDirectoryName(ctx.Path); foreach (var buffer in ctx.GLTF.buffers) @@ -573,44 +573,44 @@ public static void LoadVrmAsync(VRMImporterContext ctx, ArraySegment chunk } return Unit.Default; }) - .ContinueWith(MainThreadDispatcher.Instance.ThreadScheduler, _ => + .ContinueWith(Scheduler.ThreadPool, _ => { return glTF_VRM_Material.Parse(ctx.Json); }) - .ContinueWith(MainThreadDispatcher.Instance.UnityScheduler, x => + .ContinueWith(Scheduler.MainThread, x => { // material function ctx.CreateMaterial = VRMImporter.GetMaterialFunc(x); }) - .OnExecute(MainThreadDispatcher.Instance.UnityScheduler, parent => + .OnExecute(Scheduler.ThreadPool, parent => { // textures for (int i = 0; i < ctx.GLTF.textures.Count; ++i) { var index = i; - parent.AddTask(MainThreadDispatcher.Instance.UnityScheduler, + parent.AddTask(Scheduler.MainThread, () => gltfImporter.ImportTexture(ctx.GLTF, index)) - .ContinueWith(MainThreadDispatcher.Instance.ThreadScheduler, x => ctx.Textures.Add(x)); + .ContinueWith(Scheduler.ThreadPool, x => ctx.Textures.Add(x)); } }) - .ContinueWithCoroutine(MainThreadDispatcher.Instance.UnityScheduler, () => LoadMaterials(ctx)) - .OnExecute(MainThreadDispatcher.Instance.UnityScheduler, parent => + .ContinueWithCoroutine(Scheduler.MainThread, () => LoadMaterials(ctx)) + .OnExecute(Scheduler.ThreadPool, parent => { // meshes for (int i = 0; i < ctx.GLTF.meshes.Count; ++i) { var index = i; - parent.AddTask(MainThreadDispatcher.Instance.ThreadScheduler, + parent.AddTask(Scheduler.ThreadPool, () => gltfImporter.ReadMesh(ctx, index)) - .ContinueWith(MainThreadDispatcher.Instance.UnityScheduler, x => gltfImporter.BuildMesh(ctx, x)) - .ContinueWith(MainThreadDispatcher.Instance.ThreadScheduler, x => ctx.Meshes.Add(x)) + .ContinueWith(Scheduler.MainThread, x => gltfImporter.BuildMesh(ctx, x)) + .ContinueWith(Scheduler.ThreadPool, x => ctx.Meshes.Add(x)) ; } }) - .ContinueWithCoroutine(MainThreadDispatcher.Instance.UnityScheduler, () => LoadNodes(ctx)) - .ContinueWithCoroutine(MainThreadDispatcher.Instance.UnityScheduler, () => BuildHierarchy(ctx)) - .ContinueWith(MainThreadDispatcher.Instance.UnityScheduler, _ => VRMImporter.OnLoadModel(ctx)) - .Subscribe(MainThreadDispatcher.Instance.UnityScheduler, + .ContinueWithCoroutine(Scheduler.MainThread, () => LoadNodes(ctx)) + .ContinueWithCoroutine(Scheduler.MainThread, () => BuildHierarchy(ctx)) + .ContinueWith(Scheduler.MainThread, _ => VRMImporter.OnLoadModel(ctx)) + .Subscribe(Scheduler.MainThread, _ => { /* diff --git a/Scripts/UniTask/MainThreadDispatcher.cs b/Scripts/UniTask/MainThreadDispatcher.cs index 95fd5b0c6c..d0bd8c2089 100644 --- a/Scripts/UniTask/MainThreadDispatcher.cs +++ b/Scripts/UniTask/MainThreadDispatcher.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using UnityEngine; - namespace UniTask { /// @@ -11,37 +10,6 @@ namespace UniTask /// public class MainThreadDispatcher : MonoBehaviour { - StepScheduler m_unityScheduler; - /// - /// Dequeueとタスク実行がUnityのMainThread上であるこを保証する - /// - public StepScheduler UnityScheduler - { - get - { - if (m_unityScheduler == null) - { - m_unityScheduler = new StepScheduler(); - } - return m_unityScheduler; - } - } - - ThreadScheduler m_threadScheduler; - /// - /// Dequeuとタスク実行がWorkerThread上で実行される - /// - public ThreadScheduler ThreadScheduler - { - get - { - if (m_threadScheduler == null) - { - m_threadScheduler = new ThreadScheduler(); - } - return m_threadScheduler; - } - } [Header("Debug")] public int TaskCount; @@ -61,7 +29,7 @@ IEnumerable Ancestors(Transform t) private void Update() { - TaskCount = UnityScheduler.UpdateAndGetTaskCount(); + TaskCount = Scheduler.MainThread.UpdateAndGetTaskCount(); } static MainThreadDispatcher instance; @@ -166,10 +134,9 @@ void OnDestroy() initialized = instance != null; } - if (m_threadScheduler != null) + if (Scheduler.SingleWorkerThread != null) { - m_threadScheduler.Dispose(); - m_threadScheduler = null; + Scheduler.SingleWorkerThread.Dispose(); } } diff --git a/Scripts/UniTask/Scheduler.cs b/Scripts/UniTask/Scheduler.cs index 12fb7bb3a3..90abc3e1a7 100644 --- a/Scripts/UniTask/Scheduler.cs +++ b/Scripts/UniTask/Scheduler.cs @@ -1,6 +1,8 @@ -namespace UniTask +using System; + +namespace UniTask { - public interface IScheduler + public interface IScheduler : IDisposable { void Enqueue(TaskChain item); } diff --git a/Scripts/UniTask/StepScheduler.cs b/Scripts/UniTask/StepScheduler.cs index 7af5d3d982..a394763e95 100644 --- a/Scripts/UniTask/StepScheduler.cs +++ b/Scripts/UniTask/StepScheduler.cs @@ -1,30 +1,52 @@ namespace UniTask { - public class StepScheduler : IScheduler + public static partial class Scheduler { - LockQueue m_taskQueue = new LockQueue(); - public void Enqueue(TaskChain item) + private static StepScheduler mainThread; + + public static StepScheduler MainThread { - m_taskQueue.Enqueue(item); + get + { + if (mainThread != null) return mainThread; + mainThread = new StepScheduler(); + MainThreadDispatcher.Initialize(); + return mainThread; + } } - TaskChain m_chain; - public int UpdateAndGetTaskCount() + public class StepScheduler : IScheduler { - if (m_chain != null) + LockQueue m_taskQueue = new LockQueue(); + + public void Enqueue(TaskChain item) { - var status=m_chain.Next(); - if(status==ExecutionStatus.Continue) + m_taskQueue.Enqueue(item); + } + + TaskChain m_chain; + + public int UpdateAndGetTaskCount() + { + if (m_chain != null) { - // m_item継続中 - return m_taskQueue.Count; + var status = m_chain.Next(); + if (status == ExecutionStatus.Continue) + { + // m_item継続中 + return m_taskQueue.Count; + } + m_chain = null; } - m_chain = null; + + int count; + m_chain = m_taskQueue.Dequeue(out count); + return count; } - int count; - m_chain = m_taskQueue.Dequeue(out count); - return count; + public void Dispose() + { + } } } } diff --git a/Scripts/UniTask/TaskChain.cs b/Scripts/UniTask/TaskChain.cs index b15688b503..89b93cfe0b 100644 --- a/Scripts/UniTask/TaskChain.cs +++ b/Scripts/UniTask/TaskChain.cs @@ -32,7 +32,7 @@ public static TaskChain Schedule(ISchedulable schedulable, Action onE if (item.Enumerator.Current.Schedulder == null) { // default - MainThreadDispatcher.Instance.UnityScheduler.Enqueue(item); + Scheduler.MainThread.Enqueue(item); } else { diff --git a/Scripts/UniTask/ThreadPoolScheduler.cs b/Scripts/UniTask/ThreadPoolScheduler.cs new file mode 100644 index 0000000000..94e6316e7c --- /dev/null +++ b/Scripts/UniTask/ThreadPoolScheduler.cs @@ -0,0 +1,42 @@ +using System; + +namespace UniTask +{ + public static partial class Scheduler + { + private static IScheduler threadPool; + + public static IScheduler ThreadPool + { + get { return threadPool ?? (threadPool = new ThreadPoolScheduler()); } + } + + public class ThreadPoolScheduler : IScheduler + { + public void Enqueue(TaskChain item) + { + System.Threading.ThreadPool.QueueUserWorkItem(_ => + { + if (item == null) + { + return; + } + + while (true) + { + var status = item.Next(); + if (status != ExecutionStatus.Continue) + { + break; + } + } + + }); + } + + public void Dispose() + { + } + } + } +} diff --git a/Scripts/UniTask/ThreadScheduler.cs b/Scripts/UniTask/ThreadScheduler.cs index 24b4624385..e5a7975885 100644 --- a/Scripts/UniTask/ThreadScheduler.cs +++ b/Scripts/UniTask/ThreadScheduler.cs @@ -3,87 +3,99 @@ namespace UniTask { - public class ThreadScheduler : IScheduler, IDisposable + public static partial class Scheduler { - MonitorQueue m_queue = new MonitorQueue(); + private static IScheduler singleWorkerTrehad; - Thread m_thread; - - public ThreadScheduler() + public static IScheduler SingleWorkerThread { - // start worker thread - m_thread = new Thread(new ParameterizedThreadStart(Worker)); - m_thread.Start(m_queue); + get { return singleWorkerTrehad ?? (singleWorkerTrehad = new ThreadScheduler()); } } - static void Worker(Object arg) + public class ThreadScheduler : IScheduler { - MonitorQueue queue = (MonitorQueue)arg; - while (true) + MonitorQueue m_queue = new MonitorQueue(); + + Thread m_thread; + + public ThreadScheduler() { - var chain = queue.Dequeue(); - if (chain == null) - { - break; - } + // start worker thread + m_thread = new Thread(new ParameterizedThreadStart(Worker)); + m_thread.Start(m_queue); + } + static void Worker(Object arg) + { + MonitorQueue queue = (MonitorQueue)arg; while (true) { - var status = chain.Next(); - if (status != ExecutionStatus.Continue) + var chain = queue.Dequeue(); + if (chain == null) { break; } + + while (true) + { + var status = chain.Next(); + if (status != ExecutionStatus.Continue) + { + break; + } + } } + + // end } - // end - } + public void Enqueue(TaskChain item) + { + m_queue.Enqueue(item); + } - public void Enqueue(TaskChain item) - { - m_queue.Enqueue(item); - } + #region IDisposable Support - #region IDisposable Support - private bool disposedValue = false; // 重複する呼び出しを検出するには + private bool disposedValue = false; // 重複する呼び出しを検出するには - protected virtual void Dispose(bool disposing) - { - if (!disposedValue) + protected virtual void Dispose(bool disposing) { - if (disposing) + if (!disposedValue) { - // TODO: マネージ状態を破棄します (マネージ オブジェクト)。 - if (m_thread != null) + if (disposing) { - m_queue.Enqueue(null); - m_thread.Join(); - m_thread = null; + // TODO: マネージ状態を破棄します (マネージ オブジェクト)。 + if (m_thread != null) + { + m_queue.Enqueue(null); + m_thread.Join(); + m_thread = null; + } } - } - // TODO: アンマネージ リソース (アンマネージ オブジェクト) を解放し、下のファイナライザーをオーバーライドします。 - // TODO: 大きなフィールドを null に設定します。 + // TODO: アンマネージ リソース (アンマネージ オブジェクト) を解放し、下のファイナライザーをオーバーライドします。 + // TODO: 大きなフィールドを null に設定します。 - disposedValue = true; + disposedValue = true; + } } - } - // TODO: 上の Dispose(bool disposing) にアンマネージ リソースを解放するコードが含まれる場合にのみ、ファイナライザーをオーバーライドします。 - // ~ThreadScheduler() { - // // このコードを変更しないでください。クリーンアップ コードを上の Dispose(bool disposing) に記述します。 - // Dispose(false); - // } + // TODO: 上の Dispose(bool disposing) にアンマネージ リソースを解放するコードが含まれる場合にのみ、ファイナライザーをオーバーライドします。 + // ~ThreadScheduler() { + // // このコードを変更しないでください。クリーンアップ コードを上の Dispose(bool disposing) に記述します。 + // Dispose(false); + // } - // このコードは、破棄可能なパターンを正しく実装できるように追加されました。 - public void Dispose() - { - // このコードを変更しないでください。クリーンアップ コードを上の Dispose(bool disposing) に記述します。 - Dispose(true); - // TODO: 上のファイナライザーがオーバーライドされる場合は、次の行のコメントを解除してください。 - // GC.SuppressFinalize(this); + // このコードは、破棄可能なパターンを正しく実装できるように追加されました。 + public void Dispose() + { + // このコードを変更しないでください。クリーンアップ コードを上の Dispose(bool disposing) に記述します。 + Dispose(true); + // TODO: 上のファイナライザーがオーバーライドされる場合は、次の行のコメントを解除してください。 + // GC.SuppressFinalize(this); + } + + #endregion } - #endregion } }