| @@ -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
                    
                