/// <summary> /// Initializes a new instance of the <see cref="object"/> class. /// </summary> public Cleaner([NotNull] ContextStack <T> stack) { _stack = stack; _threadId = Thread.CurrentThread.ManagedThreadId; _oldStack = CallContext.LogicalGetData(_stack._contextKey) as string; if (_oldStack != null) { CallContext.FreeNamedDataSlot(_stack._contextKey); } _tls = _stack._stackCache.Value; // Clear the stack cache. _stack._stackCache.Value = default(KeyValuePair <string, IEnumerable <T> >); }
/// <summary> /// Initializes a new instance of the <see cref="ContextStack<T>.Disposer"/> class. /// </summary> /// <param name="stack">The stack.</param> /// <param name="value">The value.</param> public Disposer([NotNull] ContextStack <T> stack, T value) { _stack = stack; _threadId = Thread.CurrentThread.ManagedThreadId; // We use Interlocked.Increment, as it's thread safe and never overflows (wraps around). // by the time it wraps back to itself it's highly likely that the objects are no longer in use. // However, the while loop ensures we get a nice blank spot. T used; do { _key = Interlocked.Increment(ref stack._counter); } while (stack._objects.TryGetValue(_key, out used)); stack._objects.AddOrUpdate(_key, value, (k, v) => value); _oldStack = CallContext.LogicalGetData(stack._contextKey) as string; CallContext.LogicalSetData( stack._contextKey, (_oldStack == null ? string.Empty : _oldStack + "|") + _key); }