﻿<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>Ayende @ Rahien</title><link>http://ayende.com</link><description>Ayende @ Rahien</description><copyright>Copyright (C) Ayende Rahien  2004 - 2021 (c) 2026</copyright><ttl>60</ttl><item><title>Thomas Eyde commented on Wrong Answer #2: Your own ThreadLocal</title><description>@Hendry, the Close() method removes the key and value, doesn't this mean they will be collected after all.
  
  
My first working solution collected all thread slots. That doesn't seem to be necessary, so I modified it. Just keeping a local reference makes the code simpler and removes the need for additional cleanup.
  
  
A fun exercise, by the way. Too bad I need so many iterations and hints before I get it right ;)
  
  
[http://pastebin.com/d9HSepi5](http://pastebin.com/d9HSepi5)  
</description><link>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment15</link><guid>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment15</guid><pubDate>Mon, 20 Dec 2010 10:18:05 GMT</pubDate></item><item><title>Alois Kraus commented on Wrong Answer #2: Your own ThreadLocal</title><description>My Closable class needs a flag in the ctor to prevent the finalizer from beeing run when the thing is queried. Apart from this minor issue it should work. 
  
</description><link>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment14</link><guid>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment14</guid><pubDate>Mon, 20 Dec 2010 08:50:03 GMT</pubDate></item><item><title>Karan Misra commented on Wrong Answer #2: Your own ThreadLocal</title><description>How about this?
  
  
public class CloseableThreadLocal {
  
        [ThreadStatic]
  
        private static int _counter;
  
  
        [ThreadStatic]
  
        internal static Dictionary
&lt;int,&gt;
 _slots;
  
  
        public static Dictionary
&lt;int,&gt;
 Slots {
  
            get { return _slots ?? (_slots = new Dictionary
&lt;int,&gt;
()); }
  
        }
  
  
        private static Func
&lt;int GenerateThreadKey = () =&gt; string.Format("{0}{1}", Thread.CurrentThread.ManagedThreadId, _counter).GetHashCode();
  
  
        private int _threadKey = GenerateThreadKey();
  
  
        private Dictionary
&lt;int,&gt;
&gt; _threadSlots;
  
  
        private Dictionary
&lt;int,&gt;
&gt; ThreadSlots {
  
            get {
  
                return _threadSlots ?? (_threadSlots = new Dictionary
&lt;int,&gt;
&gt;());
  
  
            }
  
        }
  
  
        public /*protected internal*/ virtual Object InitialValue() {
  
            return null;
  
        }
  
  
        public virtual Object Get() {
  
            object val;
  
  
            if (Slots.TryGetValue(_threadKey, out val)) {
  
                return val;
  
            }
  
            val = InitialValue();
  
            Set(val);
  
            return val;
  
        }
  
  
        public virtual void Set(object val) {
  
            Slots[_threadKey] = val;
  
  
            lock (this) {
  
                ThreadSlots[_threadKey] = _slots;
  
                _counter++;
  
            }
  
        }
  
  
        public virtual void Close() {
  
            if (_threadSlots != null) {
  
                foreach (var values in _threadSlots)
  
                    values.Value.Remove(values.Key);
  
                _threadSlots = null;
  
            }
  
        }
  
  
        ~CloseableThreadLocal() {
  
            Close();
  
        }
  
    }
&gt;</description><link>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment13</link><guid>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment13</guid><pubDate>Mon, 20 Dec 2010 08:48:50 GMT</pubDate></item><item><title>Hendry Luk commented on Wrong Answer #2: Your own ThreadLocal</title><description>The CloseableThreadLocal will get collected, but the key (and the value) will still be referenced by the slots, and will therefore stay uncollected.
  
 Why not use WeakReference? Isn't this the exact scenario WeakReference is intended for?
</description><link>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment12</link><guid>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment12</guid><pubDate>Mon, 20 Dec 2010 06:08:03 GMT</pubDate></item><item><title>Jared Kells commented on Wrong Answer #2: Your own ThreadLocal</title><description>The finalizer runs in the GC thread.
  
  
You could change the dictionary to a concurrent dictionary and then keep a local reference to the one you are using in CloseableThreadLocal.
  
  
Something like this:
  
		private ConcurrentDictionary
&lt;object,&gt;
 _mySlots;
  
		private ConcurrentDictionary
&lt;object,&gt;
 MySlots
  
		{
  
			get { return _mySlots ?? (_mySlots = Slots); }
  
		}
  
  
  
In Get and Set use MySlots in Close() use _mySlots
  
  
</description><link>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment11</link><guid>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment11</guid><pubDate>Mon, 20 Dec 2010 01:50:22 GMT</pubDate></item><item><title>Karan Misra commented on Wrong Answer #2: Your own ThreadLocal</title><description>How about this guys? Any comments?
  
  
    public class CloseableThreadLocal {
  
        private readonly string _threadKey = typeof(CloseableThreadLocal).FullName + Thread.CurrentThread.ManagedThreadId;
  
        private Dictionary
&lt;object,&gt;
 _slots;
  
  
        [ThreadStatic]
  
        internal static Dictionary
&lt;object,&gt;
 slots;
  
  
        public static Dictionary
&lt;object,&gt;
 Slots {
  
            get { return slots ?? (slots = new Dictionary
&lt;object,&gt;
()); }
  
        }
  
  
        public /*protected internal*/ virtual Object InitialValue() {
  
            return null;
  
        }
  
  
        public virtual Object Get() {
  
            object val;
  
  
            if (Slots.TryGetValue(_threadKey, out val)) {
  
                return val;
  
            }
  
            val = InitialValue();
  
            Set(val);
  
            return val;
  
        }
  
  
        public virtual void Set(object val) {
  
            Slots[_threadKey] = val;
  
            if (_slots == null) _slots = slots;
  
        }
  
  
        public virtual void Close() {
  
            if (_slots != null)// intentionally using the field here, to avoid creating the instance
  
                _slots.Remove(_threadKey);
  
        }
  
  
        ~CloseableThreadLocal() {
  
            Close();
  
        }
  
    }
</description><link>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment10</link><guid>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment10</guid><pubDate>Sun, 19 Dec 2010 23:40:14 GMT</pubDate></item><item><title>Alois Kraus commented on Wrong Answer #2: Your own ThreadLocal</title><description>The idea is nice but he forgot to pass the context to make the finalizer work. This one would do the trick:
  
  
   public class CloseableThreadLocal
  
    {
  
        public class Closer
  
        {
  
            int Tid;
  
            public Closer(int id)
  
            {
  
                Tid = id;
  
            }
  
  
            ~Closer()
  
            {
  
                lock(CloseableThreadLocal.Slots)
  
                {
  
                    if (CloseableThreadLocal.Slots.ContainsKey(this))
  
                        CloseableThreadLocal.Slots.Remove(this);
  
                }
  
            }
  
  
            public override bool Equals(object obj)
  
            {
  
                Closer c = obj as Closer;
  
                if (c == null)
  
                    return false;
  
                return c.Tid == this.Tid;
  
            }
  
  
            public override int GetHashCode()
  
            {
  
                return Tid;
  
            }
  
        }
  
  
        internal static Dictionary
&lt;closer,&gt;
 slots = new Dictionary
&lt;closer,&gt;
();
  
  
        public static Dictionary
&lt;closer,&gt;
 Slots
  
        {
  
            get { return slots; }
  
        }
  
  
        public /*protected internal*/ virtual Object InitialValue()
  
        {
  
            return null;
  
        }
  
  
        public virtual Object Get()
  
        {
  
            object val;
  
  
            lock (Slots)
  
            {
  
                if (Slots.TryGetValue(new Closer(Thread.CurrentThread.ManagedThreadId), out val))
  
                {
  
                    return val;
  
                }
  
            }
  
            val = InitialValue();
  
            Set(val);
  
            return val;
  
        }
  
  
        public virtual void Set(object val)
  
        {
  
            lock (Slots)
  
            {
  
                Slots[new Closer(Thread.CurrentThread.ManagedThreadId)] = val;
  
            }
  
        }
  
  
        public virtual void Close()
  
        {
  
            lock (Slots)
  
            {
  
                if (slots != null)// intentionally using the field here, to avoid creating the instance
  
                {
  
                    slots.Remove(new Closer(Thread.CurrentThread.ManagedThreadId));
  
                }
  
            }
  
        }
  
    }
  
  
Yes it does not scale that well because it uses a global dictionary but until you show me the requirement that thread thrashing is a problem it is out of scope. 
</description><link>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment9</link><guid>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment9</guid><pubDate>Sun, 19 Dec 2010 22:11:15 GMT</pubDate></item><item><title>Ori commented on Wrong Answer #2: Your own ThreadLocal</title><description>ooops :)
</description><link>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment8</link><guid>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment8</guid><pubDate>Sun, 19 Dec 2010 13:33:15 GMT</pubDate></item><item><title>Ayende Rahien commented on Wrong Answer #2: Your own ThreadLocal</title><description>Ori,
  
Take a look at the class name
</description><link>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment7</link><guid>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment7</guid><pubDate>Sun, 19 Dec 2010 12:25:10 GMT</pubDate></item><item><title>Ori commented on Wrong Answer #2: Your own ThreadLocal</title><description>but why a threadstatic static backing field? seems that the dictionary was suppose to id instances by key but the threadstatic attribute allocated a new backing field per thread..
</description><link>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment6</link><guid>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment6</guid><pubDate>Sun, 19 Dec 2010 12:15:06 GMT</pubDate></item><item><title>Augi commented on Wrong Answer #2: Your own ThreadLocal</title><description>You could use WeakReference class instead of own "holder": 
[msdn.microsoft.com/.../system.weakreference.aspx](http://msdn.microsoft.com/en-us/library/system.weakreference.aspx)</description><link>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment5</link><guid>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment5</guid><pubDate>Sun, 19 Dec 2010 11:06:38 GMT</pubDate></item><item><title>Inferis commented on Wrong Answer #2: Your own ThreadLocal</title><description>The finalizer runs on another thread, so the slots field is null when the finalizer runs. The slots field on the original thread is never touched in the finalizer.
</description><link>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment4</link><guid>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment4</guid><pubDate>Sun, 19 Dec 2010 10:58:36 GMT</pubDate></item><item><title>Ayende Rahien commented on Wrong Answer #2: Your own ThreadLocal</title><description>Ashic,
  
Nope, that is a bug in the wrong example, fixed now
</description><link>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment3</link><guid>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment3</guid><pubDate>Sun, 19 Dec 2010 10:21:20 GMT</pubDate></item><item><title>tobi commented on Wrong Answer #2: Your own ThreadLocal</title><description>beautiful technique.
</description><link>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment2</link><guid>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment2</guid><pubDate>Sun, 19 Dec 2010 10:18:06 GMT</pubDate></item><item><title>ashic commented on Wrong Answer #2: Your own ThreadLocal</title><description>We seem to be setting it with the key as "holder" but when removing, we're doing slots.Remove(this). Could that be it?
</description><link>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment1</link><guid>http://ayende.com/4728/wrong-answer-2-your-own-threadlocal#comment1</guid><pubDate>Sun, 19 Dec 2010 10:16:19 GMT</pubDate></item></channel></rss>