123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- #if UNITY_WEBGL && !UNITY_EDITOR
- #define SINGLE_THREAD
- #endif
- using System.Collections.Generic;
- using System.Threading;
- namespace Pathfinding.Util {
-
-
-
-
-
-
-
-
- public class ParallelWorkQueue<T> {
-
-
-
-
- public System.Action<T, int> action;
-
- public readonly int threadCount;
-
- readonly Queue<T> queue;
- readonly int initialCount;
- #if !SINGLE_THREAD
- ManualResetEvent[] waitEvents;
- System.Exception innerException;
- #endif
- public ParallelWorkQueue (Queue<T> queue) {
- this.queue = queue;
- initialCount = queue.Count;
- #if SINGLE_THREAD
- threadCount = 1;
- #else
- threadCount = System.Math.Min(initialCount, System.Math.Max(1, AstarPath.CalculateThreadCount(ThreadCount.AutomaticHighLoad)));
- #endif
- }
-
-
-
- public IEnumerable<int> Run (int progressTimeoutMillis) {
- if (initialCount != queue.Count) throw new System.InvalidOperationException("Queue has been modified since the constructor");
-
-
-
-
- if (initialCount == 0) yield break;
- #if SINGLE_THREAD
-
- for (int i = 0; i < initialCount; i++) {
- action(queue.Dequeue(), 0);
- yield return i + 1;
- }
- #else
-
- waitEvents = new ManualResetEvent[threadCount];
- for (int i = 0; i < waitEvents.Length; i++) {
- waitEvents[i] = new ManualResetEvent(false);
- #if NETFX_CORE
-
- int threadIndex = i;
- System.Threading.Tasks.Task.Run(() => RunTask(threadIndex));
- #else
- ThreadPool.QueueUserWorkItem(threadIndex => RunTask((int)threadIndex), i);
- #endif
- }
- while (!WaitHandle.WaitAll(waitEvents, progressTimeoutMillis)) {
- int count;
- lock (queue) count = queue.Count;
- yield return initialCount - count;
- }
- if (innerException != null) throw innerException;
- #endif
- }
- #if !SINGLE_THREAD
- void RunTask (int threadIndex) {
- try {
- while (true) {
- T tile;
- lock (queue) {
- if (queue.Count == 0) return;
- tile = queue.Dequeue();
- }
- action(tile, threadIndex);
- }
- } catch (System.Exception e) {
- innerException = e;
-
- lock (queue) queue.Clear();
- } finally {
- waitEvents[threadIndex].Set();
- }
- }
- #endif
- }
- }
|