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