AnswerYour own ThreadLocal

time to read 4 min | 616 words

Originally posted at 12/15/2010

Well, the problem on our last answer was that we didn’t protect ourselves from multi threaded access to the slots variable. Here is the code with this fixed:

public class CloseableThreadLocal
{
    [ThreadStatic]
    public static Dictionary<object, object> slots;

    private readonly object holder = new object();
    private Dictionary<object, object> capturedSlots;

    private Dictionary<object, object> Slots
    {
        get
        {
            if (slots == null)
                slots = new Dictionary<object, object>();
            capturedSlots = slots;
            return slots;
        }
    }


    public /*protected internal*/ virtual Object InitialValue()
    {
        return null;
    }

    public virtual Object Get()
    {
        object val;

        lock (Slots)
        {
            if (Slots.TryGetValue(holder, out val))
            {
                return val;
            }
        }
        val = InitialValue();
        Set(val);
        return val;
    }

    public virtual void Set(object val)
    {
        lock (Slots)
        {
            Slots[holder] = val;
        }
    }

    public virtual void Close()
    {
        GC.SuppressFinalize(this);
        if (capturedSlots != null)
            capturedSlots.Remove(this);
    }

    ~CloseableThreadLocal()
    {
        if (capturedSlots == null)
            return;
        lock (capturedSlots)
            capturedSlots.Remove(holder);
    }
}

Is this it? Are there still issues that we need to handle?

More posts in "Answer" series:

  1. (05 Jan 2023) what does this code print?
  2. (15 Dec 2022) What does this code print?
  3. (07 Apr 2022) Why is this code broken?
  4. (20 Jan 2017) What does this code do?
  5. (16 Aug 2011) Modifying execution approaches
  6. (30 Apr 2011) Stopping the leaks
  7. (24 Dec 2010) This code should never hit production
  8. (21 Dec 2010) Your own ThreadLocal
  9. (11 Feb 2010) Debugging a resource leak
  10. (03 Sep 2009) The lazy loaded inheritance many to one association OR/M conundrum
  11. (04 Sep 2008) Don't stop with the first DSL abstraction
  12. (12 Jun 2008) How many tests?