Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
05/25/11 17:22:58 (14 years ago)
Author:
epitzer
Message:

fixed synchronization issue in evaluation cache and simplified event handling (#1516)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/EvaluationCache.cs

    r6265 r6291  
    4444
    4545    #region Types
    46     private class CacheEntry {
    47 
    48       public string Key { get; private set; }
    49       public double Value { get; set; }
     46    private sealed class CacheEntry {
     47
     48      public readonly string Key;
     49      public double Value;
    5050
    5151      public CacheEntry(string key, double value) {
     
    5454      }
    5555
    56       public CacheEntry(string key) : this(key, 0) { }
     56      public CacheEntry(string key) {
     57        Key = key;
     58      }
    5759
    5860      public override bool Equals(object obj) {
     
    7880    private LinkedList<CacheEntry> list;
    7981    private Dictionary<CacheEntry, LinkedListNode<CacheEntry>> index;
     82
    8083    private HashSet<string> activeEvaluations = new HashSet<string>();
    81     private object cacheLock = new object();
    82     private object evaluationLock = new object();
    83     private AutoResetEvent evaluationDone = new AutoResetEvent(false);
     84    private object cacheLock = new object();   
    8485    #endregion
    8586
     
    8889      get { return VSImageLibrary.Database; }
    8990    }
    90     public int Size {
    91       get {
    92         lock (cacheLock) {
    93           return index.Count;
    94         }
    95       }
    96     }
    97     public int ActiveEvaluations {
    98       get {
    99         lock (evaluationLock) {
    100           return activeEvaluations.Count;
    101         }
    102       }
    103     }
     91    public int Size { get { lock (cacheLock) return index.Count; } }
     92    public int ActiveEvaluations { get { lock (cacheLock) return activeEvaluations.Count; } }
     93
    10494    [Storable]
    10595    public int Hits { get; private set; }
     
    10797
    10898    #region events
    109     public event EventHandler SizeChanged;
    110     public event EventHandler HitsChanged;
    111     public event EventHandler ActiveEvalutionsChanged;
    112 
    113     protected virtual void OnSizeChanged() {
    114       EventHandler handler = SizeChanged;
    115       if (handler != null)
    116         handler(this, EventArgs.Empty);
    117     }
    118     protected virtual void OnHitsChanged() {
    119       EventHandler handler = HitsChanged;
    120       if (handler != null)
    121         handler(this, EventArgs.Empty);
    122     }
    123     protected virtual void OnActiveEvalutionsChanged() {
    124       EventHandler handler = ActiveEvalutionsChanged;
     99    public event EventHandler Changed;
     100
     101    protected virtual void OnChanged() {
     102      EventHandler handler = Changed;
    125103      if (handler != null)
    126104        handler(this, EventArgs.Empty);
     
    195173      if (Capacity < 0)
    196174        throw new ArgumentOutOfRangeException("Cache capacity cannot be less than zero");
    197       Trim();
     175      lock (cacheLock)
     176        Trim();
     177      OnChanged();
    198178    }
    199179    #endregion
     
    206186        Hits = 0;
    207187      }
    208       OnSizeChanged();
    209       OnHitsChanged();
     188      OnChanged();
    210189    }
    211190
     
    214193      LinkedListNode<CacheEntry> node;
    215194      bool lockTaken = false;
    216       try {
     195      bool waited = false;
     196      try {       
    217197        Monitor.Enter(cacheLock, ref lockTaken);
    218         if (index.TryGetValue(entry, out node)) {
    219           list.Remove(node);
    220           list.AddLast(node);
    221           Hits++;
    222           lockTaken = false;
    223           Monitor.Exit(cacheLock);
    224           OnHitsChanged();
    225           return node.Value.Value;
    226         } else {
    227           lockTaken = false;
    228           Monitor.Exit(cacheLock);
    229           return Evaluate(message, evaluate, entry);
     198        while (true) {
     199          if (index.TryGetValue(entry, out node)) {
     200            list.Remove(node);
     201            list.AddLast(node);
     202            Hits++;
     203            lockTaken = false;
     204            Monitor.Exit(cacheLock);
     205            OnChanged();
     206            return node.Value.Value;
     207          } else {
     208            if (!waited && activeEvaluations.Contains(entry.Key)) {
     209              while (activeEvaluations.Contains(entry.Key))
     210                Monitor.Wait(cacheLock);
     211              waited = true;
     212            } else {
     213              activeEvaluations.Add(entry.Key);
     214              lockTaken = false;
     215              Monitor.Exit(cacheLock);
     216              OnChanged();
     217              try {
     218                entry.Value = evaluate(message);
     219                Monitor.Enter(cacheLock, ref lockTaken);
     220                index[entry] = list.AddLast(entry);
     221                Trim();
     222              } finally {
     223                if (!lockTaken)
     224                  Monitor.Enter(cacheLock, ref lockTaken);
     225                activeEvaluations.Remove(entry.Key);
     226                Monitor.PulseAll(cacheLock);
     227                lockTaken = false;
     228                Monitor.Exit(cacheLock);
     229              }
     230              OnChanged();
     231              return entry.Value;
     232            }
     233          }
    230234        }
    231235      } finally {
     
    235239    }
    236240
    237     private double Evaluate(SolutionMessage message, Evaluator evaluate, CacheEntry entry) {
    238       bool lockTaken = false;
    239       try {
    240         Monitor.Enter(evaluationLock, ref lockTaken);
    241         if (activeEvaluations.Contains(entry.Key)) {
    242           while (activeEvaluations.Contains(entry.Key)) {
    243             lockTaken = false;
    244             Monitor.Exit(evaluationLock);
    245             evaluationDone.WaitOne();
    246             Monitor.Enter(evaluationLock, ref lockTaken);
    247           }
    248           lock (cacheLock) {
    249             return index[entry].Value.Value;
    250           }
    251         } else {
    252           activeEvaluations.Add(entry.Key);
    253           lockTaken = false;
    254           Monitor.Exit(evaluationLock);
    255           OnActiveEvalutionsChanged();
    256           try {
    257             entry.Value = evaluate(message);
    258             lock (cacheLock) {
    259               index[entry] = list.AddLast(entry);
    260             }
    261             Trim();
    262           } finally {
    263             lock (evaluationLock) {
    264               activeEvaluations.Remove(entry.Key);
    265               evaluationDone.Set();
    266             }
    267             OnActiveEvalutionsChanged();
    268           }
    269           return entry.Value;
    270         }
    271       } finally {
    272         if (lockTaken)
    273           Monitor.Exit(evaluationLock);
    274       }
    275     }
    276 
    277241    private void Trim() {
    278       lock (cacheLock) {
    279         while (list.Count > Capacity) {
    280           LinkedListNode<CacheEntry> item = list.First;
    281           list.Remove(item);
    282           index.Remove(item.Value);
    283         }
    284       }
    285       OnSizeChanged();
     242      while (list.Count > Capacity) {
     243        LinkedListNode<CacheEntry> item = list.First;
     244        list.Remove(item);
     245        index.Remove(item.Value);
     246      }
    286247    }
    287248
     
    318279    }
    319280    #endregion
    320   } 
     281  }
    321282}
Note: See TracChangeset for help on using the changeset viewer.