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