Example #1
0
            /* the previous value is stored in order to avoid the overhead of an stack or linked list */

            public ThreadVariableValueScope(ThreadVariable <T> key, T value, ThreadVariableValueScope previous)
            {
                threadId      = Thread.CurrentThread.ManagedThreadId;
                this.key      = key;
                this.value    = value;
                this.previous = previous;
            }
Example #2
0
        /// <summary>
        /// Returns a scope for the <paramref name="value"/>. The value is held in the
        /// current thread, until the scope is disposed.
        /// </summary>
        /// <remarks>
        /// Within the scope, the value will be available via <see cref="Current"/> and
        /// <see cref="CurrentOrDefault"/>, <see cref="HasCurrent"/> will always
        /// be <value>true</value>.
        /// </remarks>
        public IDisposable Use(T value)
        {
            ThreadVariableValueScope old;
            var v = EnsuredValues;

            v.TryGetValue(this, out old);
            return(v[this] = new ThreadVariableValueScope(this, value, old));
        }
Example #3
0
        /// <summary>
        /// Disposes the scope <paramref name="scopeToDispose"/> and it's other
        /// nested scopes.
        /// </summary>
        private void DisposeScope(ThreadVariableValueScope scopeToDispose)
        {
            // 1) The programmer simply did an error if he tried to dispose a scope on a different thread
            // 2) If the garbage collection takes care of disposal, it will get an error and ignore it
            if (Thread.CurrentThread.ManagedThreadId != scopeToDispose.threadId)
            {
                throw new InvalidOperationException("The thread variable value scope "
                                                    + "has to be disposed on the same thread it was created on!");
            }

            /* Let's say we have three scopes: outer, middle and inner.
             *
             * When disposing 'inner', usually the value is
             * recovered to 'middle'.
             * But if 'middle' is disposed before 'inner',
             * 'inner' should be disposed automatically, too.
             *
             * Else, disposing 'inner' afterwards, would end in
             * setting the current value to 'middle' - which
             * already is disposed
             */

            /* start on the current scope wich is always scopeToDispose
             * or one of its inner scopes - actually the inner most one */
            var v = EnsuredValues;
            ThreadVariableValueScope innerMost;

            v.TryGetValue(this, out innerMost);

            // dispose all inner scopes
            while (innerMost != scopeToDispose)
            {
                innerMost.MarkAsDisposed();
                innerMost = innerMost.previous;
            }

            // mark current one as disposed
            scopeToDispose.MarkAsDisposed();

            // remove, or recover previous value
            if (scopeToDispose.previous == null)
            {
                v.Remove(this);
            }
            else
            {
                v[this] = scopeToDispose.previous;
            }
        }