You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by di...@apache.org on 2009/08/04 23:40:16 UTC

svn commit: r800992 - in /incubator/lucene.net/trunk/C#/src/Lucene.Net: Search/CachingSpanFilter.cs Search/CachingWrapperFilter.cs Search/FieldCacheImpl.cs SupportClass.cs

Author: digy
Date: Tue Aug  4 21:40:15 2009
New Revision: 800992

URL: http://svn.apache.org/viewvc?rev=800992&view=rev
Log:
LUCENENET-106 for 2.4.0

Modified:
    incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/CachingSpanFilter.cs
    incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/CachingWrapperFilter.cs
    incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldCacheImpl.cs
    incubator/lucene.net/trunk/C#/src/Lucene.Net/SupportClass.cs

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/CachingSpanFilter.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/CachingSpanFilter.cs?rev=800992&r1=800991&r2=800992&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/CachingSpanFilter.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/CachingSpanFilter.cs Tue Aug  4 21:40:15 2009
@@ -62,7 +62,7 @@
 			SpanFilterResult result = null;
 			if (cache == null)
 			{
-				cache = new System.Collections.Hashtable();
+                cache = new SupportClass.WeakHashTable();
 			}
 			
 			lock (cache.SyncRoot)

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/CachingWrapperFilter.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/CachingWrapperFilter.cs?rev=800992&r1=800991&r2=800992&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/CachingWrapperFilter.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/CachingWrapperFilter.cs Tue Aug  4 21:40:15 2009
@@ -49,7 +49,7 @@
 		{
 			if (cache == null)
 			{
-				cache = new System.Collections.Hashtable();
+                cache = new SupportClass.WeakHashTable();
 			}
 			
 			lock (cache.SyncRoot)

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldCacheImpl.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Search/FieldCacheImpl.cs?rev=800992&r1=800991&r2=800992&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldCacheImpl.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Search/FieldCacheImpl.cs Tue Aug  4 21:40:15 2009
@@ -563,7 +563,7 @@
 		/// <summary>Expert: Internal cache. </summary>
 		internal abstract class Cache
 		{
-			private System.Collections.IDictionary readerCache = new System.Collections.Hashtable();
+            private System.Collections.IDictionary readerCache = new SupportClass.WeakHashTable();
 			
 			protected internal abstract object CreateValue(IndexReader reader, object key);
 			

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/SupportClass.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/SupportClass.cs?rev=800992&r1=800991&r2=800992&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/SupportClass.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/SupportClass.cs Tue Aug  4 21:40:15 2009
@@ -16,6 +16,7 @@
  */
 
 using System;
+using System.Collections;
 
 /// <summary>
 /// This interface should be implemented by any class whose instances are intended 
@@ -1303,4 +1304,247 @@
             }
         }
     }
+	
+	#region WEAKHASHTABLE
+    /// <summary>
+    /// A Hashtable which holds weak references to its keys so they
+    /// can be collected during GC. 
+    /// </summary>
+    [System.Diagnostics.DebuggerDisplay("Count = {Values.Count}")]
+    public class WeakHashTable : Hashtable, IEnumerable
+    {
+        /// <summary>
+        /// A weak referene wrapper for the hashtable keys. Whenever a key\value pair 
+        /// is added to the hashtable, the key is wrapped using a WeakKey. WeakKey saves the
+        /// value of the original object hashcode for fast comparison.
+        /// </summary>
+        class WeakKey : WeakReference
+        {
+            int hashCode;
+
+            public WeakKey(object key)
+                : base(key)
+            {
+                if (key == null)
+                    throw new ArgumentNullException("key");
+
+                hashCode = key.GetHashCode();
+            }
+
+            public override int GetHashCode()
+            {
+                return hashCode;
+            }
+        }
+
+        /// <summary>
+        /// A Dictionary enumerator which wraps the original hashtable enumerator 
+        /// and performs 2 tasks: Extract the real key from a WeakKey and skip keys
+        /// that were already collected.
+        /// </summary>
+        class WeakDictionaryEnumerator : IDictionaryEnumerator
+        {
+            IDictionaryEnumerator baseEnumerator;
+            object currentKey;
+            object currentValue;
+
+            public WeakDictionaryEnumerator(IDictionaryEnumerator baseEnumerator)
+            {
+                this.baseEnumerator = baseEnumerator;
+            }
+
+            public DictionaryEntry Entry
+            {
+                get
+                {
+                    return new DictionaryEntry(this.currentKey, this.currentValue);
+                }
+            }
+
+            public object Key
+            {
+                get
+                {
+                    return this.currentKey;
+                }
+            }
+
+            public object Value
+            {
+                get
+                {
+                    return this.currentValue;
+                }
+            }
+
+            public object Current
+            {
+                get
+                {
+                    return Entry;
+                }
+            }
+
+            public bool MoveNext()
+            {
+                while (baseEnumerator.MoveNext())
+                {
+                    object key = ((WeakKey)baseEnumerator.Key).Target;
+                    if (key != null)
+                    {
+                        this.currentKey = key;
+                        this.currentValue = baseEnumerator.Value;
+                        return true;
+                    }
+                }
+                return false;
+            }
+
+            public void Reset()
+            {
+                baseEnumerator.Reset();
+                this.currentKey = null;
+                this.currentValue = null;
+            }
+        }
+
+
+        /// <summary>
+        /// Serves as a simple "GC Monitor" that indicates whether cleanup is needed. 
+        /// If collectableObject.IsAlive is false, GC has occurred and we should perform cleanup
+        /// </summary>
+        WeakReference collectableObject = new WeakReference(new Object());
+
+        /// <summary>
+        /// Customize the hashtable lookup process by overriding KeyEquals. KeyEquals
+        /// will compare both WeakKey to WeakKey and WeakKey to real keys
+        /// </summary>
+        protected override bool KeyEquals(object x, object y)
+        {
+            if (x == y)
+                return true;
+
+            if (x is WeakKey)
+            {
+                x = ((WeakKey)x).Target;
+                if (x == null)
+                    return false;
+            }
+
+            if (y is WeakKey)
+            {
+                y = ((WeakKey)y).Target;
+                if (y == null)
+                    return false;
+            }
+
+            return x.Equals(y);
+        }
+
+        protected override int GetHash(object key)
+        {
+            return key.GetHashCode();
+        }
+
+        /// <summary>
+        /// Perform cleanup if GC occurred
+        /// </summary>
+        private void CleanIfNeeded()
+        {
+            if (collectableObject.Target == null)
+            {
+                Clean();
+                collectableObject = new WeakReference(new Object());
+            }
+        }
+
+        /// <summary>
+        /// Iterate over all keys and remove keys that were collected
+        /// </summary>
+        private void Clean()
+        {
+            ArrayList keysToDelete = new ArrayList();
+            foreach (WeakKey wtk in base.Keys)
+            {
+                if (!wtk.IsAlive)
+                {
+                    keysToDelete.Add(wtk);
+                }
+            }
+
+            foreach (WeakKey wtk in keysToDelete)
+                Remove(wtk);
+        }
+
+
+        /// <summary>
+        /// Wrap each key with a WeakKey and add it to the hashtable
+        /// </summary>
+        public override void Add(object key, object value)
+        {
+            CleanIfNeeded();
+            base.Add(new WeakKey(key), value);
+        }
+
+        public override IDictionaryEnumerator GetEnumerator()
+        {
+            return new WeakDictionaryEnumerator(base.GetEnumerator());
+        }
+
+        /// <summary>
+        /// Create a temporary copy of the real keys and return that
+        /// </summary>
+        public override ICollection Keys
+        {
+            get
+            {
+                ArrayList keys = new ArrayList(Count);
+                foreach (WeakKey key in base.Keys)
+                {
+                    object realKey = key.Target;
+                    if (realKey != null)
+                        keys.Add(realKey);
+                }
+                return keys;
+            }
+        }
+
+        public override object this[object key]
+        {
+            get
+            {
+                return base[key];
+            }
+            set
+            {
+                CleanIfNeeded();
+                base[new WeakKey(key)] = value;
+            }
+        }
+
+        public override void CopyTo(Array array, int index)
+        {
+            int arrayIndex = index;
+            foreach (DictionaryEntry de in this)
+            {
+                array.SetValue(de, arrayIndex++);
+            }
+        }
+
+        public override int Count
+        {
+            get
+            {
+                CleanIfNeeded();
+                return base.Count;
+            }
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+    }
+    #endregion
+
 }