Mercurial > pub > ImplabNet
comparison Implab/Parallels/DispatchPool.cs @ 16:5a4b735ba669 promises
sync
| author | cin |
|---|---|
| date | Thu, 07 Nov 2013 20:20:26 +0400 |
| parents | 0f982f9b7d4d |
| children | 7cd4a843b4e4 |
comparison
equal
deleted
inserted
replaced
| 15:0f982f9b7d4d | 16:5a4b735ba669 |
|---|---|
| 61 return m_exitRequired != 0; | 61 return m_exitRequired != 0; |
| 62 } | 62 } |
| 63 } | 63 } |
| 64 | 64 |
| 65 bool StartWorker() { | 65 bool StartWorker() { |
| 66 var current = m_runningThreads; | 66 int current; |
| 67 // use spins to allocate slot for the new thread | 67 // use spins to allocate slot for the new thread |
| 68 do { | 68 do { |
| 69 current = m_runningThreads; | |
| 69 if (current >= m_maxThreads || m_exitRequired != 0) | 70 if (current >= m_maxThreads || m_exitRequired != 0) |
| 70 // no more slots left or the pool has been disposed | 71 // no more slots left or the pool has been disposed |
| 71 return false; | 72 return false; |
| 72 } while (current != Interlocked.CompareExchange(ref m_runningThreads, current + 1, current)); | 73 } while (current != Interlocked.CompareExchange(ref m_runningThreads, current + 1, current)); |
| 73 | 74 |
| 82 return true; | 83 return true; |
| 83 } | 84 } |
| 84 | 85 |
| 85 protected abstract bool TryDequeue(out TUnit unit); | 86 protected abstract bool TryDequeue(out TUnit unit); |
| 86 | 87 |
| 87 protected virtual void WakeNewWorker() { | 88 protected virtual void WakeNewWorker(bool extend) { |
| 88 if (m_suspended > 0) | 89 if (m_suspended > 0) |
| 89 m_hasTasks.Set(); | 90 m_hasTasks.Set(); |
| 90 else | 91 else |
| 91 StartWorker(); | 92 StartWorker(); |
| 93 } | |
| 94 | |
| 95 /// <summary> | |
| 96 /// Запускает либо новый поток, если раньше не было ни одного потока, либо устанавливает событие пробуждение одного спящего потока | |
| 97 /// </summary> | |
| 98 protected void StartIfIdle() { | |
| 99 int threads; | |
| 100 do { | |
| 101 | |
| 102 } | |
| 103 } | |
| 104 | |
| 105 protected virtual void Suspend() { | |
| 106 m_hasTasks.WaitOne(); | |
| 92 } | 107 } |
| 93 | 108 |
| 94 bool FetchTask(out TUnit unit) { | 109 bool FetchTask(out TUnit unit) { |
| 95 do { | 110 do { |
| 96 // exit if requested | 111 // exit if requested |
| 97 if (m_exitRequired != 0) { | 112 if (m_exitRequired != 0) { |
| 98 // release the thread slot | 113 // release the thread slot |
| 99 int running; | 114 var running = Interlocked.Decrement(ref m_runningThreads); |
| 100 do { | |
| 101 running = m_runningThreads; | |
| 102 } while (running != Interlocked.CompareExchange(ref m_runningThreads, running - 1, running)); | |
| 103 running--; | |
| 104 | |
| 105 if (running == 0) // it was the last worker | 115 if (running == 0) // it was the last worker |
| 106 m_hasTasks.Dispose(); | 116 m_hasTasks.Dispose(); |
| 107 else | 117 else |
| 108 m_hasTasks.Set(); // release next worker | 118 m_hasTasks.Set(); // release next worker |
| 109 unit = default(TUnit); | 119 unit = default(TUnit); |
| 110 return false; | 120 return false; |
| 111 } | 121 } |
| 112 | 122 |
| 113 // fetch task | 123 // fetch task |
| 114 if (TryDequeue(out unit)) { | 124 if (TryDequeue(out unit)) { |
| 115 WakeNewWorker(); | 125 WakeNewWorker(true); |
| 116 return true; | 126 return true; |
| 117 } | 127 } |
| 118 | 128 |
| 119 //no tasks left, exit if the thread is no longer needed | 129 //no tasks left, exit if the thread is no longer needed |
| 120 int runningThreads; | 130 int runningThreads; |
| 121 bool exit = true; | 131 bool exit = true; |
| 122 do { | 132 do { |
| 123 runningThreads = m_runningThreads; | 133 runningThreads = m_runningThreads; |
| 124 if (runningThreads <= m_minThreads) { | 134 if (runningThreads <= m_minThreads) { |
| 135 // check wheather this is the last thread and we have tasks | |
| 136 | |
| 125 exit = false; | 137 exit = false; |
| 126 break; | 138 break; |
| 127 } | 139 } |
| 128 } while (runningThreads != Interlocked.CompareExchange(ref m_runningThreads, runningThreads - 1, runningThreads)); | 140 } while (runningThreads != Interlocked.CompareExchange(ref m_runningThreads, runningThreads - 1, runningThreads)); |
| 129 | 141 |
| 130 if (exit) { | 142 if (exit) { |
| 131 Interlocked.Decrement(ref m_runningThreads); | |
| 132 return false; | 143 return false; |
| 133 } | 144 } |
| 134 | 145 |
| 135 // keep this thread and wait | 146 // entering suspend state |
| 136 Interlocked.Increment(ref m_suspended); | 147 Interlocked.Increment(ref m_suspended); |
| 137 m_hasTasks.WaitOne(); | 148 // keep this thread and wait |
| 149 Suspend(); | |
| 138 Interlocked.Decrement(ref m_suspended); | 150 Interlocked.Decrement(ref m_suspended); |
| 139 } while (true); | 151 } while (true); |
| 140 } | 152 } |
| 141 | 153 |
| 142 protected abstract void InvokeUnit(TUnit unit); | 154 protected abstract void InvokeUnit(TUnit unit); |
