| @@ -103,15 +103,15 namespace Implab.Test { | |||||
| 103 |
|
103 | |||
| 104 | Assert.AreEqual(5, pool.PoolSize); |
|
104 | Assert.AreEqual(5, pool.PoolSize); | |
| 105 |
|
105 | |||
| 106 | pool.Invoke(() => { Thread.Sleep(1000000); return 10; }); |
|
106 | pool.Invoke(() => { Thread.Sleep(100000000); return 10; }); | |
| 107 | pool.Invoke(() => { Thread.Sleep(1000000); return 10; }); |
|
107 | pool.Invoke(() => { Thread.Sleep(100000000); return 10; }); | |
| 108 | pool.Invoke(() => { Thread.Sleep(1000000); return 10; }); |
|
108 | pool.Invoke(() => { Thread.Sleep(100000000); return 10; }); | |
| 109 |
|
109 | |||
| 110 | Assert.AreEqual(5, pool.PoolSize); |
|
110 | Assert.AreEqual(5, pool.PoolSize); | |
| 111 |
|
111 | |||
| 112 | for (int i = 0; i < 100; i++) |
|
112 | for (int i = 0; i < 100; i++) | |
| 113 | pool.Invoke(() => { Thread.Sleep(1000000); return 10; }); |
|
113 | pool.Invoke(() => { Thread.Sleep(100000000); return 10; }); | |
| 114 |
Thread.Sleep( |
|
114 | Thread.Sleep(200); | |
| 115 | Assert.AreEqual(10, pool.PoolSize); |
|
115 | Assert.AreEqual(10, pool.PoolSize); | |
| 116 |
|
116 | |||
| 117 | pool.Dispose(); |
|
117 | pool.Dispose(); | |
| @@ -244,7 +244,7 namespace Implab.Test { | |||||
| 244 | [TestMethod] |
|
244 | [TestMethod] | |
| 245 | public void ChainedMapTest() { |
|
245 | public void ChainedMapTest() { | |
| 246 |
|
246 | |||
| 247 |
using (var pool = new WorkerPool(0 |
|
247 | using (var pool = new WorkerPool(4,4,0)) { | |
| 248 | int count = 10000; |
|
248 | int count = 10000; | |
| 249 |
|
249 | |||
| 250 | double[] args = new double[count]; |
|
250 | double[] args = new double[count]; | |
| 1 | NO CONTENT: modified file, binary diff hidden |
|
NO CONTENT: modified file, binary diff hidden |
| @@ -83,14 +83,42 namespace Implab.Parallels { | |||||
| 83 | return signals; |
|
83 | return signals; | |
| 84 | } |
|
84 | } | |
| 85 |
|
85 | |||
|
|
86 | bool FetchSignalOrWait(int timeout) { | |||
|
|
87 | var start = Environment.TickCount; | |||
|
|
88 | ||||
|
|
89 | // ΠΎΠ·Π½Π°ΡΠ°Π΅Ρ, ΡΡΠΎ ΠΏΠΎΡΠΎΠΊ Π²Π»Π°Π΄Π΅Π΅Ρ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΎΠΉ ΠΈ ΠΏΡΠΈ ΡΡΠΏΠ΅ΡΠ½ΠΎΠΌ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΠΈ ΡΠΈΠ³Π½Π°Π»Π° Π΄ΠΎΠ»ΠΆΠ΅Π½ | |||
|
|
90 | // Π΅Π΅ Π²Π΅ΡΠ½ΡΡΡ, ΡΡΠΎΠ±Ρ Π΄ΡΡΠ³ΠΎΠΉ ΠΎΠΆΠΈΠ΄Π°ΡΡΠΈΠΉ ΠΏΠΎΡΠΎΠΊ ΡΠΌΠΎΠ³ | |||
|
|
91 | bool hasLock = false; | |||
|
|
92 | do { | |||
|
|
93 | int signals; | |||
|
|
94 | do { | |||
|
|
95 | signals = m_wakeEvents; | |||
|
|
96 | if (signals == 0) | |||
|
|
97 | break; | |||
|
|
98 | } while (Interlocked.CompareExchange(ref m_wakeEvents, signals - 1, signals) != signals); | |||
|
|
99 | ||||
|
|
100 | if (signals >= 1) { | |||
|
|
101 | if (signals > 1 && hasLock) | |||
|
|
102 | m_hasTasks.Set(); | |||
|
|
103 | return true; | |||
|
|
104 | } | |||
|
|
105 | ||||
|
|
106 | if (timeout != -1) | |||
|
|
107 | timeout = Math.Max(0, timeout - (Environment.TickCount - start)); | |||
|
|
108 | ||||
|
|
109 | // Π΅ΡΠ»ΠΈ ΡΠΈΠ³Π½Π°Π»ΠΎΠ² Π±ΠΎΠ»ΡΡΠ΅ Π½Π΅ ΠΎΡΡΠ°Π»ΠΎΡΡ, ΡΠΎ ΠΏΠ΅ΡΠ²ΡΠΉ ΠΏΠΎΡΠΎΠΊ, ΠΊΠΎΡΠΎΡΡΠΉ Π΄ΠΎΡΠ΅Π» ΡΡΠ΄Π° ΡΠ±ΡΠΎΡΠΈΡ ΡΠΎΠ±ΡΡΠΈΠ΅ | |||
|
|
110 | // ΠΈ ΡΠΉΠ΄Π΅Ρ Π½Π° ΠΏΡΡΡΠΎΠΉ ΡΠΈΠΊΠ», ΠΏΠΎΡΠ»Π΅ ΡΠ΅Π³ΠΎ Π·Π°Π±Π»ΠΎΠΊΠΈΡΡΠ΅ΡΡΡ | |||
|
|
111 | ||||
|
|
112 | hasLock = true; | |||
|
|
113 | } while (m_hasTasks.WaitOne(timeout)); | |||
|
|
114 | ||||
|
|
115 | return false; | |||
|
|
116 | } | |||
|
|
117 | ||||
| 86 | bool Sleep(int timeout) { |
|
118 | bool Sleep(int timeout) { | |
| 87 | Interlocked.Increment(ref m_sleepingThreads); |
|
119 | Interlocked.Increment(ref m_sleepingThreads); | |
| 88 |
if ( |
|
120 | if (FetchSignalOrWait(timeout)) { | |
| 89 | // this is autoreset event, only one thread can run this block simultaneously |
|
121 | Interlocked.Decrement(ref m_sleepingThreads); | |
| 90 | var sleeping = Interlocked.Decrement(ref m_sleepingThreads); |
|
|||
| 91 | if (Interlocked.Decrement(ref m_wakeEvents) > 0) |
|
|||
| 92 | m_hasTasks.Set(); // wake next worker |
|
|||
| 93 |
|
||||
| 94 | return true; |
|
122 | return true; | |
| 95 | } else { |
|
123 | } else { | |
| 96 | Interlocked.Decrement(ref m_sleepingThreads); |
|
124 | Interlocked.Decrement(ref m_sleepingThreads); | |
| @@ -106,6 +134,8 namespace Implab.Parallels { | |||||
| 106 | if (m_exitRequired != 0) |
|
134 | if (m_exitRequired != 0) | |
| 107 | return; |
|
135 | return; | |
| 108 | if (m_sleepingThreads > m_wakeEvents) { |
|
136 | if (m_sleepingThreads > m_wakeEvents) { | |
|
|
137 | //Console.WriteLine("Waking threads (sleeps {0}, pending {1})", m_sleepingThreads, m_wakeEvents); | |||
|
|
138 | ||||
| 109 | // all sleeping threads may gone |
|
139 | // all sleeping threads may gone | |
| 110 | SignalThread(); // wake a sleeping thread; |
|
140 | SignalThread(); // wake a sleeping thread; | |
| 111 |
|
141 | |||
| @@ -130,8 +160,6 namespace Implab.Parallels { | |||||
| 130 | bool last; |
|
160 | bool last; | |
| 131 | bool requestExit; |
|
161 | bool requestExit; | |
| 132 |
|
162 | |||
| 133 |
|
||||
| 134 |
|
||||
| 135 | // if threads have a timeout before releasing |
|
163 | // if threads have a timeout before releasing | |
| 136 | if (m_releaseTimeout > 0) |
|
164 | if (m_releaseTimeout > 0) | |
| 137 | requestExit = !Sleep(m_releaseTimeout); |
|
165 | requestExit = !Sleep(m_releaseTimeout); | |
| @@ -242,8 +270,8 namespace Implab.Parallels { | |||||
| 242 |
|
270 | |||
| 243 | void Worker() { |
|
271 | void Worker() { | |
| 244 | TUnit unit; |
|
272 | TUnit unit; | |
|
|
273 | //Console.WriteLine("{0}: Active", Thread.CurrentThread.ManagedThreadId); | |||
| 245 | Interlocked.Increment(ref m_activeThreads); |
|
274 | Interlocked.Increment(ref m_activeThreads); | |
| 246 | Sleep(0); // remove wake request if the new thread is started |
|
|||
| 247 | do { |
|
275 | do { | |
| 248 | // exit if requested |
|
276 | // exit if requested | |
| 249 | if (m_exitRequired != 0) { |
|
277 | if (m_exitRequired != 0) { | |
| @@ -269,10 +297,10 namespace Implab.Parallels { | |||||
| 269 | // keep this thread and wait |
|
297 | // keep this thread and wait | |
| 270 | if (!Suspend()) |
|
298 | if (!Suspend()) | |
| 271 | break; |
|
299 | break; | |
| 272 |
|
300 | //Console.WriteLine("{0}: Awake", Thread.CurrentThread.ManagedThreadId); | ||
| 273 | Interlocked.Increment(ref m_activeThreads); |
|
301 | Interlocked.Increment(ref m_activeThreads); | |
| 274 | } while (true); |
|
302 | } while (true); | |
| 275 |
|
303 | //Console.WriteLine("{0}: Exited", Thread.CurrentThread.ManagedThreadId); | ||
| 276 | } |
|
304 | } | |
| 277 |
|
305 | |||
| 278 | protected virtual void Dispose(bool disposing) { |
|
306 | protected virtual void Dispose(bool disposing) { | |
General Comments 0
You need to be logged in to leave comments.
Login now
