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); |