Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
05/17/11 14:02:33 (13 years ago)
Author:
epitzer
Message:

Use system wait handles instead of potential spin lock for done signal (#1350)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/PersistenceSpeedUp/HeuristicLab.Persistence/3.3/Default/Xml/AsyncBuffer.cs

    r6211 r6220  
    22using System.Collections;
    33using System.Collections.Generic;
    4 using System.Linq;
    54using System.Threading;
    65
    76namespace HeuristicLab.Persistence.Default.Xml {
    87
    9   public class AsyncBuffer<T> : IDisposable, IEnumerable<T>, IEnumerable {
     8  public class AsyncBuffer<T> : IEnumerable<T>, IEnumerable {
    109
    1110    private IEnumerator<T> it;
     
    1413    private object queueLock;
    1514    private AutoResetEvent elementAdded;
     15    private ManualResetEvent done;
    1616
    1717    private Thread thread;
    18     private ManualResetEventSlim done;
    1918
    2019    private Exception exception;
     
    3029      queueLock = new object();
    3130      elementAdded = new AutoResetEvent(false);
     31      done = new ManualResetEvent(false);
    3232      thread = new Thread(Run);
    33       done = new ManualResetEventSlim(false);
    3433      thread.Start();
    3534    }
    3635
    3736    private void Run() {
     37      bool hasLock = false;
    3838      try {
    3939        while (it.MoveNext()) {
     
    4646      } catch (Exception x) {
    4747        exception = x;
     48      } finally {
     49        if (hasLock)
     50          Monitor.Exit(queueLock);
    4851      }
    4952      done.Set();
     53    }
     54
     55    private IEnumerator<T> RealGetEnumerator(LockIndicator li) {
     56      Monitor.Enter(queueLock, ref li.HasLock);
     57      while (!done.WaitOne(0) || queue.Count > 0) {
     58        while (queue.Count == 0 && !done.WaitOne(0)) {
     59          li.HasLock = false;
     60          Monitor.Exit(queueLock);
     61          AutoResetEvent.WaitAny(new WaitHandle[] { done, elementAdded });
     62          Monitor.Enter(queueLock, ref li.HasLock);
     63        }
     64        if (queue.Count > 0) {
     65          T element = queue.Dequeue();
     66          li.HasLock = false;
     67          Monitor.Exit(queueLock);
     68          yield return element;
     69          Monitor.Enter(queueLock, ref li.HasLock);
     70        }
     71      }
     72      li.HasLock = false;
     73      Monitor.Exit(queueLock);
     74      if (exception != null)
     75        throw exception;
    5076    }
    5177
     
    6187      }
    6288    }
    63 
    64     private IEnumerator<T> RealGetEnumerator(LockIndicator li) {
    65       Monitor.Enter(queueLock, ref li.HasLock);
    66       while (!done.IsSet || queue.Any()) {
    67         while (!queue.Any() && !done.IsSet) {
    68           li.HasLock = false;
    69           Monitor.Exit(queueLock);
    70           AutoResetEvent.WaitAny(new WaitHandle[] { done.WaitHandle, elementAdded });
    71           Monitor.Enter(queueLock, ref li.HasLock);
    72         }
    73         if (queue.Any()) {
    74           T element = queue.Peek();
    75           li.HasLock = false;
    76           Monitor.Exit(queueLock);
    77           yield return element;
    78           Monitor.Enter(queueLock, ref li.HasLock);
    79           queue.Dequeue();
    80         }
    81       }
    82       li.HasLock = false;
    83       Monitor.Exit(queueLock);
    84       if (exception != null)
    85         throw exception;
    86     }
    8789    #endregion
    8890
     
    9294    }
    9395    #endregion
    94 
    95     #region IDisposable Members
    96     public void Dispose() {
    97       if (elementAdded != null)
    98         elementAdded.Dispose();
    99       if (done != null)
    100         done.Dispose();
    101     }
    102     #endregion
    10396  }
    10497}
Note: See TracChangeset for help on using the changeset viewer.