Index: trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/EvaluationCache.cs
===================================================================
--- trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/EvaluationCache.cs	(revision 6265)
+++ trunk/sources/HeuristicLab.Problems.ExternalEvaluation/3.3/EvaluationCache.cs	(revision 6291)
@@ -44,8 +44,8 @@
 
     #region Types
-    private class CacheEntry {
-
-      public string Key { get; private set; }
-      public double Value { get; set; }
+    private sealed class CacheEntry {
+
+      public readonly string Key;
+      public double Value;
 
       public CacheEntry(string key, double value) {
@@ -54,5 +54,7 @@
       }
 
-      public CacheEntry(string key) : this(key, 0) { }
+      public CacheEntry(string key) {
+        Key = key;
+      }
 
       public override bool Equals(object obj) {
@@ -78,8 +80,7 @@
     private LinkedList<CacheEntry> list;
     private Dictionary<CacheEntry, LinkedListNode<CacheEntry>> index;
+
     private HashSet<string> activeEvaluations = new HashSet<string>();
-    private object cacheLock = new object();
-    private object evaluationLock = new object();
-    private AutoResetEvent evaluationDone = new AutoResetEvent(false);
+    private object cacheLock = new object();    
     #endregion
 
@@ -88,18 +89,7 @@
       get { return VSImageLibrary.Database; }
     }
-    public int Size {
-      get {
-        lock (cacheLock) {
-          return index.Count;
-        }
-      }
-    }
-    public int ActiveEvaluations {
-      get {
-        lock (evaluationLock) {
-          return activeEvaluations.Count;
-        }
-      }
-    }
+    public int Size { get { lock (cacheLock) return index.Count; } }
+    public int ActiveEvaluations { get { lock (cacheLock) return activeEvaluations.Count; } }
+
     [Storable]
     public int Hits { get; private set; }
@@ -107,20 +97,8 @@
 
     #region events
-    public event EventHandler SizeChanged;
-    public event EventHandler HitsChanged;
-    public event EventHandler ActiveEvalutionsChanged;
-
-    protected virtual void OnSizeChanged() {
-      EventHandler handler = SizeChanged;
-      if (handler != null)
-        handler(this, EventArgs.Empty);
-    }
-    protected virtual void OnHitsChanged() {
-      EventHandler handler = HitsChanged;
-      if (handler != null)
-        handler(this, EventArgs.Empty);
-    }
-    protected virtual void OnActiveEvalutionsChanged() {
-      EventHandler handler = ActiveEvalutionsChanged;
+    public event EventHandler Changed;
+
+    protected virtual void OnChanged() {
+      EventHandler handler = Changed;
       if (handler != null)
         handler(this, EventArgs.Empty);
@@ -195,5 +173,7 @@
       if (Capacity < 0)
         throw new ArgumentOutOfRangeException("Cache capacity cannot be less than zero");
-      Trim();
+      lock (cacheLock)
+        Trim();
+      OnChanged();
     }
     #endregion
@@ -206,6 +186,5 @@
         Hits = 0;
       }
-      OnSizeChanged();
-      OnHitsChanged();
+      OnChanged();
     }
 
@@ -214,18 +193,43 @@
       LinkedListNode<CacheEntry> node;
       bool lockTaken = false;
-      try {
+      bool waited = false;
+      try {        
         Monitor.Enter(cacheLock, ref lockTaken);
-        if (index.TryGetValue(entry, out node)) {
-          list.Remove(node);
-          list.AddLast(node);
-          Hits++;
-          lockTaken = false;
-          Monitor.Exit(cacheLock);
-          OnHitsChanged();
-          return node.Value.Value;
-        } else {
-          lockTaken = false;
-          Monitor.Exit(cacheLock);
-          return Evaluate(message, evaluate, entry);
+        while (true) {
+          if (index.TryGetValue(entry, out node)) {
+            list.Remove(node);
+            list.AddLast(node);
+            Hits++;
+            lockTaken = false;
+            Monitor.Exit(cacheLock);
+            OnChanged();
+            return node.Value.Value;
+          } else {
+            if (!waited && activeEvaluations.Contains(entry.Key)) {
+              while (activeEvaluations.Contains(entry.Key))
+                Monitor.Wait(cacheLock);
+              waited = true;
+            } else {
+              activeEvaluations.Add(entry.Key);
+              lockTaken = false;
+              Monitor.Exit(cacheLock);
+              OnChanged();
+              try {
+                entry.Value = evaluate(message);
+                Monitor.Enter(cacheLock, ref lockTaken);
+                index[entry] = list.AddLast(entry);
+                Trim();
+              } finally {
+                if (!lockTaken)
+                  Monitor.Enter(cacheLock, ref lockTaken);
+                activeEvaluations.Remove(entry.Key);
+                Monitor.PulseAll(cacheLock);
+                lockTaken = false;
+                Monitor.Exit(cacheLock);
+              }
+              OnChanged();
+              return entry.Value;
+            }
+          }
         }
       } finally {
@@ -235,53 +239,10 @@
     }
 
-    private double Evaluate(SolutionMessage message, Evaluator evaluate, CacheEntry entry) {
-      bool lockTaken = false;
-      try {
-        Monitor.Enter(evaluationLock, ref lockTaken);
-        if (activeEvaluations.Contains(entry.Key)) {
-          while (activeEvaluations.Contains(entry.Key)) {
-            lockTaken = false;
-            Monitor.Exit(evaluationLock);
-            evaluationDone.WaitOne();
-            Monitor.Enter(evaluationLock, ref lockTaken);
-          }
-          lock (cacheLock) {
-            return index[entry].Value.Value;
-          }
-        } else {
-          activeEvaluations.Add(entry.Key);
-          lockTaken = false;
-          Monitor.Exit(evaluationLock);
-          OnActiveEvalutionsChanged();
-          try {
-            entry.Value = evaluate(message);
-            lock (cacheLock) {
-              index[entry] = list.AddLast(entry);
-            }
-            Trim();
-          } finally {
-            lock (evaluationLock) {
-              activeEvaluations.Remove(entry.Key);
-              evaluationDone.Set();
-            }
-            OnActiveEvalutionsChanged();
-          }
-          return entry.Value;
-        }
-      } finally {
-        if (lockTaken)
-          Monitor.Exit(evaluationLock);
-      }
-    }
-
     private void Trim() {
-      lock (cacheLock) {
-        while (list.Count > Capacity) {
-          LinkedListNode<CacheEntry> item = list.First;
-          list.Remove(item);
-          index.Remove(item.Value);
-        }
-      }
-      OnSizeChanged();
+      while (list.Count > Capacity) {
+        LinkedListNode<CacheEntry> item = list.First;
+        list.Remove(item);
+        index.Remove(item.Value);
+      }
     }
 
@@ -318,4 +279,4 @@
     }
     #endregion
-  }  
+  }
 }
