18 using System.Threading;
19 using System.Collections.Generic;
20 using System.Collections.Concurrent;
21 using System.Runtime.CompilerServices;
25 internal class WeightedWorkQueue
28 private bool _removed;
29 private Action _singleCallWork;
30 private readonly List<WorkItem> _workQueue;
35 private AutoResetEvent _workAvailableEvent;
40 public ThreadPriority ThreadPriority => ThreadPriority.Lowest;
45 public WeightedWorkQueue()
47 _workQueue =
new List<WorkItem>();
48 _workAvailableEvent =
new AutoResetEvent(
false);
55 public void WorkerThread(ConcurrentQueue<WorkItem> newWork, AutoResetEvent newWorkEvent)
57 var waitHandles =
new WaitHandle[] { _workAvailableEvent, newWorkEvent };
58 var waitedPreviousLoop = 0;
62 if (!newWork.TryDequeue(out workItem))
67 if(_singleCallWork !=
null)
73 catch (Exception exception)
76 Logging.Log.Error(exception);
79 _singleCallWork =
null;
83 WaitHandle.WaitAny(waitHandles, Math.Min(1 + (waitedPreviousLoop * 10), 250));
95 waitedPreviousLoop = 0;
96 if (!workItem.Work(WeightedWorkScheduler.WorkBatchSize))
101 catch (Exception exception)
104 Logging.Log.Error(exception);
113 private void Add(WorkItem work)
115 _workQueue.Add(work);
122 public void AddSingleCall(Action work)
124 _singleCallWork = work;
125 _workAvailableEvent.Set();
132 private void Remove(WorkItem workItem)
134 _workQueue.Remove(workItem);
142 [MethodImpl(MethodImplOptions.AggressiveInlining)]
143 protected WorkItem Get()
145 var count = _workQueue.Count;
150 var countFactor = (10 + 10 / count) / 10;
156 _pointer = Math.Min(_pointer, count - 1);
159 var initial = _pointer;
162 var item = _workQueue[_pointer++];
163 if (_pointer >= count)
171 _workQueue.Sort(WorkItem.Compare);
175 if (item.UpdateWeight() < WeightedWorkScheduler.MaxWorkWeight * countFactor)
179 }
while (initial != _pointer);