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 2011/08/28 01:16:04 UTC

[Lucene.Net] svn commit: r1162458 - in /incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/core/Util: CloseableThreadLocal-old.cs CloseableThreadLocal.cs

Author: digy
Date: Sat Aug 27 23:16:04 2011
New Revision: 1162458

URL: http://svn.apache.org/viewvc?rev=1162458&view=rev
Log:
[LUCENENET-358]
New Implementation of CloseableThreadLocal for 2.9.4g

Added:
    incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/core/Util/CloseableThreadLocal-old.cs
Modified:
    incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/core/Util/CloseableThreadLocal.cs

Added: incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/core/Util/CloseableThreadLocal-old.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/core/Util/CloseableThreadLocal-old.cs?rev=1162458&view=auto
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/core/Util/CloseableThreadLocal-old.cs (added)
+++ incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/core/Util/CloseableThreadLocal-old.cs Sat Aug 27 23:16:04 2011
@@ -0,0 +1,94 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Lucene.Net.Util
+{
+	
+	/// <summary>Java's builtin ThreadLocal has a serious flaw:
+	/// it can take an arbitrarily long amount of time to
+	/// dereference the things you had stored in it, even once the
+	/// ThreadLocal instance itself is no longer referenced.
+	/// This is because there is single, master map stored for
+	/// each thread, which all ThreadLocals share, and that
+	/// master map only periodically purges "stale" entries.
+	/// 
+	/// While not technically a memory leak, because eventually
+	/// the memory will be reclaimed, it can take a long time
+	/// and you can easily hit OutOfMemoryError because from the
+	/// GC's standpoint the stale entries are not reclaimaible.
+	/// 
+	/// This class works around that, by only enrolling
+	/// WeakReference values into the ThreadLocal, and
+	/// separately holding a hard reference to each stored
+	/// value.  When you call {@link #close}, these hard
+	/// references are cleared and then GC is freely able to
+	/// reclaim space by objects stored in it. 
+	/// </summary>
+	
+	public class CloseableThreadLocal<T>
+	{
+		
+		[ThreadStatic]
+        static Support.WeakDictionary<CloseableThreadLocal<T>, T> slots;
+		
+		public virtual T InitialValue()
+		{
+			return default(T);
+		}
+
+        public virtual T Get()
+        {
+            T value;
+
+            if (slots == null)
+            {
+                value = InitialValue();
+                if (value != null)
+                    Set(value);
+
+                return value;
+            }
+
+            if (slots.ContainsKey(this))
+            {
+                return slots[this];
+            }
+            else
+            {
+                value = InitialValue();
+                slots[this] = value;
+                return value;
+            }
+        }
+		
+		public virtual void  Set(T object_Renamed)
+		{
+            if (slots == null)
+                slots = new Support.WeakDictionary<CloseableThreadLocal<T>, T>();
+
+			slots[this] = object_Renamed;	
+		}
+		
+		public virtual void  Close()
+		{
+            if(slots != null)
+                slots.Remove(this);
+		}
+	}
+}
\ No newline at end of file

Modified: incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/core/Util/CloseableThreadLocal.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/core/Util/CloseableThreadLocal.cs?rev=1162458&r1=1162457&r2=1162458&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/core/Util/CloseableThreadLocal.cs (original)
+++ incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/core/Util/CloseableThreadLocal.cs Sat Aug 27 23:16:04 2011
@@ -16,79 +16,146 @@
  */
 
 using System;
+using System.Collections.Generic;
+using System.Threading;
 
 namespace Lucene.Net.Util
 {
-	
-	/// <summary>Java's builtin ThreadLocal has a serious flaw:
-	/// it can take an arbitrarily long amount of time to
-	/// dereference the things you had stored in it, even once the
-	/// ThreadLocal instance itself is no longer referenced.
-	/// This is because there is single, master map stored for
-	/// each thread, which all ThreadLocals share, and that
-	/// master map only periodically purges "stale" entries.
-	/// 
-	/// While not technically a memory leak, because eventually
-	/// the memory will be reclaimed, it can take a long time
-	/// and you can easily hit OutOfMemoryError because from the
-	/// GC's standpoint the stale entries are not reclaimaible.
-	/// 
-	/// This class works around that, by only enrolling
-	/// WeakReference values into the ThreadLocal, and
-	/// separately holding a hard reference to each stored
-	/// value.  When you call {@link #close}, these hard
-	/// references are cleared and then GC is freely able to
-	/// reclaim space by objects stored in it. 
-	/// </summary>
-	
-	public class CloseableThreadLocal<T>
-	{
-		
-		[ThreadStatic]
-        static Support.WeakDictionary<CloseableThreadLocal<T>, T> slots;
-		
-		public virtual T InitialValue()
-		{
-			return default(T);
-		}
 
-        public virtual T Get()
+    /// <summary>Java's builtin ThreadLocal has a serious flaw:
+    /// it can take an arbitrarily long amount of time to
+    /// dereference the things you had stored in it, even once the
+    /// ThreadLocal instance itself is no longer referenced.
+    /// This is because there is single, master map stored for
+    /// each thread, which all ThreadLocals share, and that
+    /// master map only periodically purges "stale" entries.
+    /// 
+    /// While not technically a memory leak, because eventually
+    /// the memory will be reclaimed, it can take a long time
+    /// and you can easily hit OutOfMemoryError because from the
+    /// GC's standpoint the stale entries are not reclaimaible.
+    /// 
+    /// This class works around that, by only enrolling
+    /// WeakReference values into the ThreadLocal, and
+    /// separately holding a hard reference to each stored
+    /// value.  When you call {@link #close}, these hard
+    /// references are cleared and then GC is freely able to
+    /// reclaim space by objects stored in it. 
+    /// </summary>
+    /// 
+
+    public class CloseableThreadLocal<T> where T : class
+    {
+        private ThreadLocal<WeakReference> t = new ThreadLocal<WeakReference>();
+
+        private Dictionary<Thread, T> hardRefs = new Dictionary<Thread, T>();
+
+
+        public virtual T InitialValue()
         {
-            T value;
+            return null;
+        }
 
-            if (slots == null)
+        public virtual T Get()
+        {
+            WeakReference weakRef = t.Get();
+            if (weakRef == null)
             {
-                value = InitialValue();
-                if (value != null)
-                    Set(value);
-
-                return value;
+                T iv = InitialValue();
+                if (iv != null)
+                {
+                    Set(iv);
+                    return iv;
+                }
+                else
+                    return null;
             }
+            else
+            {
+                return (T)weakRef.Get();
+            }
+        }
+
+        public virtual void Set(T @object)
+        {
+            t.Set(new WeakReference(@object));
 
-            if (slots.ContainsKey(this))
+            lock (hardRefs)
             {
-                return slots[this];
+                //hardRefs[Thread.CurrentThread] = @object;
+                hardRefs.Add(Thread.CurrentThread,@object);
+
+                // Purge dead threads
+                foreach (var thread in new List<Thread>(hardRefs.Keys))
+                {
+                    if (!thread.IsAlive)
+                        hardRefs.Remove(thread);
+                }
+
             }
-            else
+        }
+
+        public virtual void Close()
+        {
+            // Clear the hard refs; then, the only remaining refs to
+            // all values we were storing are weak (unless somewhere
+            // else is still using them) and so GC may reclaim them:
+            hardRefs = null;
+            // Take care of the current thread right now; others will be
+            // taken care of via the WeakReferences.
+            if (t != null)
             {
-                value = InitialValue();
-                slots[this] = value;
-                return value;
+                t.Remove();
             }
+            t = null;
+        }
+    }
+
+    internal static class CloseableThreadLocalExtensions
+    {
+        public static void Set<T>(this ThreadLocal<T> t, T val)
+        {
+            t.Value = val;
+        }
+
+        public static T Get<T>(this ThreadLocal<T> t)
+        {
+            return t.Value;
         }
-		
-		public virtual void  Set(T object_Renamed)
-		{
-            if (slots == null)
-                slots = new Support.WeakDictionary<CloseableThreadLocal<T>, T>();
-
-			slots[this] = object_Renamed;	
-		}
-		
-		public virtual void  Close()
-		{
-            if(slots != null)
-                slots.Remove(this);
-		}
-	}
+
+        public static void Remove<T>(this ThreadLocal<T> t)
+        {
+            t.Dispose();
+        }
+
+        public static object Get(this WeakReference w)
+        {
+            return w.Target;
+        }
+    }
+
+
+    // {{DIGY}} 
+    // This causes security exception in Medium Trust 
+    // TestCase: Lucene.Net.Support.TestMediumTrust.TestIndexAndSearch
+    //class WeakReference<T> : WeakReference where T : class
+    //{
+    //    public WeakReference(T target) : base(target)
+    //    {
+    //    }
+
+    //    public WeakReference(T target, bool trackResurrection)  : base(target, trackResurrection)
+    //    {
+    //    }
+
+    //    public new T Target
+    //    {
+    //        get { return (T)base.Target; }
+    //    }
+
+    //    public T Get()
+    //    {
+    //        return (T)base.Target;
+    //    }
+    //}
 }
\ No newline at end of file