Example #1
0
 internal Bucket(BucketSet owningSet)
 {
     _timedOut = false;
     _index = -1;
     _size = 1024; // A possible design change here is to have this scale dynamically based on load.
     _transactions = new InternalTransaction[_size];
     _owningSet = owningSet;
 }
Example #2
0
 internal Bucket(BucketSet owningSet)
 {
     _timedOut     = false;
     _index        = -1;
     _size         = 1024; // A possible design change here is to have this scale dynamically based on load.
     _transactions = new InternalTransaction[_size];
     _owningSet    = owningSet;
 }
 internal TransactionTable()
 {
     this.timer = new Timer(new TimerCallback(this.ThreadTimer), null, -1, this.timerInterval);
     this.timerEnabled = false;
     this.timerInterval = 0x200;
     this.ticks = 0L;
     this.headBucketSet = new BucketSet(this, 0x7fffffffffffffffL);
     this.rwLock = new CheapUnfairReaderWriterLock();
 }
Example #4
0
 internal TransactionTable()
 {
     this.timer         = new Timer(new TimerCallback(this.ThreadTimer), null, -1, this.timerInterval);
     this.timerEnabled  = false;
     this.timerInterval = 0x200;
     this.ticks         = 0L;
     this.headBucketSet = new BucketSet(this, 0x7fffffffffffffffL);
     this.rwLock        = new CheapUnfairReaderWriterLock();
 }
 private void AddIter(InternalTransaction txNew)
 {
     BucketSet headBucketSet = this.headBucketSet;
     while (headBucketSet.AbsoluteTimeout != txNew.AbsoluteTimeout)
     {
         BucketSet set3 = null;
         do
         {
             WeakReference nextSetWeak = (WeakReference) headBucketSet.nextSetWeak;
             BucketSet target = null;
             if (nextSetWeak != null)
             {
                 target = (BucketSet) nextSetWeak.Target;
             }
             if (target == null)
             {
                 BucketSet set6 = new BucketSet(this, txNew.AbsoluteTimeout);
                 WeakReference reference5 = new WeakReference(set6);
                 WeakReference reference4 = (WeakReference) Interlocked.CompareExchange(ref headBucketSet.nextSetWeak, reference5, nextSetWeak);
                 if (reference4 == nextSetWeak)
                 {
                     set6.prevSet = headBucketSet;
                 }
             }
             else
             {
                 set3 = headBucketSet;
                 headBucketSet = target;
             }
         }
         while (headBucketSet.AbsoluteTimeout > txNew.AbsoluteTimeout);
         if (headBucketSet.AbsoluteTimeout != txNew.AbsoluteTimeout)
         {
             BucketSet set2 = new BucketSet(this, txNew.AbsoluteTimeout);
             WeakReference reference3 = new WeakReference(set2);
             set2.nextSetWeak = set3.nextSetWeak;
             WeakReference reference2 = (WeakReference) Interlocked.CompareExchange(ref set3.nextSetWeak, reference3, set2.nextSetWeak);
             if (reference2 == set2.nextSetWeak)
             {
                 if (reference2 != null)
                 {
                     BucketSet set5 = (BucketSet) reference2.Target;
                     if (set5 != null)
                     {
                         set5.prevSet = set2;
                     }
                 }
                 set2.prevSet = headBucketSet;
             }
             headBucketSet = set3;
             set3 = null;
         }
     }
     headBucketSet.Add(txNew);
 }
Example #6
0
        private void AddIter(InternalTransaction txNew)
        {
            BucketSet headBucketSet = this.headBucketSet;

            while (headBucketSet.AbsoluteTimeout != txNew.AbsoluteTimeout)
            {
                BucketSet set3 = null;
                do
                {
                    WeakReference nextSetWeak = (WeakReference)headBucketSet.nextSetWeak;
                    BucketSet     target      = null;
                    if (nextSetWeak != null)
                    {
                        target = (BucketSet)nextSetWeak.Target;
                    }
                    if (target == null)
                    {
                        BucketSet     set6       = new BucketSet(this, txNew.AbsoluteTimeout);
                        WeakReference reference5 = new WeakReference(set6);
                        WeakReference reference4 = (WeakReference)Interlocked.CompareExchange(ref headBucketSet.nextSetWeak, reference5, nextSetWeak);
                        if (reference4 == nextSetWeak)
                        {
                            set6.prevSet = headBucketSet;
                        }
                    }
                    else
                    {
                        set3          = headBucketSet;
                        headBucketSet = target;
                    }
                }while (headBucketSet.AbsoluteTimeout > txNew.AbsoluteTimeout);
                if (headBucketSet.AbsoluteTimeout != txNew.AbsoluteTimeout)
                {
                    BucketSet     set2       = new BucketSet(this, txNew.AbsoluteTimeout);
                    WeakReference reference3 = new WeakReference(set2);
                    set2.nextSetWeak = set3.nextSetWeak;
                    WeakReference reference2 = (WeakReference)Interlocked.CompareExchange(ref set3.nextSetWeak, reference3, set2.nextSetWeak);
                    if (reference2 == set2.nextSetWeak)
                    {
                        if (reference2 != null)
                        {
                            BucketSet set5 = (BucketSet)reference2.Target;
                            if (set5 != null)
                            {
                                set5.prevSet = set2;
                            }
                        }
                        set2.prevSet = headBucketSet;
                    }
                    headBucketSet = set3;
                    set3          = null;
                }
            }
            headBucketSet.Add(txNew);
        }
Example #7
0
        internal TransactionTable()
        {
            // Create a timer that is initially disabled by specifing an Infinite time to the first interval
            _timer = new Timer(new TimerCallback(ThreadTimer), null, Timeout.Infinite, _timerInterval);

            // Note that the timer is disabled
            _timerEnabled = false;

            // Store the timer interval
            _timerInterval = 1 << TransactionTable.timerInternalExponent;

            // Ticks start off at zero.
            _ticks = 0;

            // The head of the list is long.MaxValue.  It contains all of the transactions that for
            // some reason or other don't have a timeout.
            _headBucketSet = new BucketSet(this, long.MaxValue);

            // Allocate the lock
            _rwLock = new CheapUnfairReaderWriterLock();
        }
Example #8
0
        // Process a timer event
        private void ThreadTimer(Object state)
        {
            //
            // Theory of operation.
            //
            // To timeout transactions we must walk down the list starting from the head
            // until we find a link with an absolute timeout that is greater than our own.
            // At that point everything further down in the list is elegable to be timed
            // out.  So simply remove that link in the list and walk down from that point
            // timing out any transaction that is found.
            //

            // There could be a race between this callback being queued and the timer
            // being disabled.  If we get here when the timer is disabled, just return.
            if (!_timerEnabled)
            {
                return;
            }

            // Increment the number of ticks
            _ticks++;
            _lastTimerTime = DateTime.UtcNow.Ticks;

            //
            // First find the starting point of transactions that should time out.  Every transaction after
            // that point will timeout so once we've found it then it is just a matter of traversing the
            // structure.
            //
            BucketSet lastBucketSet    = null;
            BucketSet currentBucketSet = _headBucketSet; // The list always has a head.

            // Acquire a writer lock before checking to see if we should disable the timer.
            // Adding of transactions acquires a reader lock and might insert a new BucketSet.
            // If that races with our check for a BucketSet existing, we may not timeout that
            // transaction that is being added.
            WeakReference nextWeakSet   = null;
            BucketSet     nextBucketSet = null;

            nextWeakSet = (WeakReference)currentBucketSet.nextSetWeak;
            if (nextWeakSet != null)
            {
                nextBucketSet = (BucketSet)nextWeakSet.Target;
            }

            if (nextBucketSet == null)
            {
                _rwLock.EnterWriteLock();
                try
                {
                    // Access the nextBucketSet again in writer lock to account for any race before disabling the timeout.
                    nextWeakSet = (WeakReference)currentBucketSet.nextSetWeak;
                    if (nextWeakSet != null)
                    {
                        nextBucketSet = (BucketSet)nextWeakSet.Target;
                    }

                    if (nextBucketSet == null)
                    {
                        //
                        // Special case to allow for disabling the timer.
                        //
                        // If there are no transactions on the timeout list we can disable the
                        // timer.
                        if (!_timer.Change(Timeout.Infinite, Timeout.Infinite))
                        {
                            throw TransactionException.CreateInvalidOperationException(
                                      SR.TraceSourceLtm,
                                      SR.UnexpectedTimerFailure,
                                      null
                                      );
                        }
                        _timerEnabled = false;

                        return;
                    }
                }
                finally
                {
                    _rwLock.ExitWriteLock();
                }
            }

            // Note it is slightly subtle that we always skip the head node.  This is done
            // on purpose because the head node contains transactions with essentially
            // an infinite timeout.
            do
            {
                do
                {
                    nextWeakSet = (WeakReference)currentBucketSet.nextSetWeak;
                    if (nextWeakSet == null)
                    {
                        // Nothing more to do.
                        return;
                    }

                    nextBucketSet = (BucketSet)nextWeakSet.Target;
                    if (nextBucketSet == null)
                    {
                        // Again nothing more to do.
                        return;
                    }
                    lastBucketSet    = currentBucketSet;
                    currentBucketSet = nextBucketSet;
                }while (currentBucketSet.AbsoluteTimeout > _ticks);

                //
                // Pinch off the list at this point making sure it is still the correct set.
                //
                // Note: We may lose a race with an "Add" thread that is inserting a BucketSet in this location in
                // the list. If that happens, this CompareExchange will not be performed and the returned abortingSetsWeak
                // value will NOT equal nextWeakSet. But we check for that and if this condition occurs, this iteration of
                // the timer thread will simply return, not timing out any transactions. When the next timer interval
                // expires, the thread will walk the list again, find the appropriate BucketSet to pinch off, and
                // then time out the transactions. This means that it is possible for a transaction to live a bit longer,
                // but not much.
                WeakReference abortingSetsWeak =
                    (WeakReference)Interlocked.CompareExchange(ref lastBucketSet.nextSetWeak, null, nextWeakSet);

                if (abortingSetsWeak == nextWeakSet)
                {
                    // Yea - now proceed to abort the transactions.
                    BucketSet abortingBucketSets = null;

                    do
                    {
                        if (abortingSetsWeak != null)
                        {
                            abortingBucketSets = (BucketSet)abortingSetsWeak.Target;
                        }
                        else
                        {
                            abortingBucketSets = null;
                        }
                        if (abortingBucketSets != null)
                        {
                            abortingBucketSets.TimeoutTransactions();
                            abortingSetsWeak = (WeakReference)abortingBucketSets.nextSetWeak;
                        }
                    }while (abortingBucketSets != null);

                    // That's all we needed to do.
                    break;
                }

                // We missed pulling the right transactions off.  Loop back up and try again.
                currentBucketSet = lastBucketSet;
            }while (true);
        }
Example #9
0
        private void AddIter(InternalTransaction txNew)
        {
            //
            // Theory of operation.
            //
            // Note that the head bucket contains any transaction with essentially infinite
            // timeout (long.MaxValue).  The list is sorted in decending order.  To add
            // a node the code must walk down the list looking for a set of bucket that matches
            // the absolute timeout value for the transaction.  When it is found it passes
            // the insert down to that set.
            //
            // An importent thing to note about the list is that forward links are all weak
            // references and reverse links are all strong references.  This allows the GC
            // to clean up old links in the list so that they don't need to be removed manually.
            // However if there is still a rooted strong reference to an old link in the
            // chain that link wont fall off the list because there is a strong reference held
            // forward.
            //

            BucketSet currentBucketSet = _headBucketSet;

            while (currentBucketSet.AbsoluteTimeout != txNew.AbsoluteTimeout)
            {
                BucketSet lastBucketSet = null;
                do
                {
                    WeakReference nextSetWeak   = (WeakReference)currentBucketSet.nextSetWeak;
                    BucketSet     nextBucketSet = null;
                    if (nextSetWeak != null)
                    {
                        nextBucketSet = (BucketSet)nextSetWeak.Target;
                    }

                    if (nextBucketSet == null)
                    {
                        //
                        // We've reached the end of the list either because nextSetWeak was null or
                        // because its reference was collected.  This code doesn't care.  Make a new
                        // set, attempt to attach it and move on.
                        //
                        BucketSet     newBucketSet = new BucketSet(this, txNew.AbsoluteTimeout);
                        WeakReference newSetWeak   = new WeakReference(newBucketSet);

                        WeakReference oldNextSetWeak = (WeakReference)Interlocked.CompareExchange(
                            ref currentBucketSet.nextSetWeak, newSetWeak, nextSetWeak);
                        if (oldNextSetWeak == nextSetWeak)
                        {
                            // Ladies and Gentlemen we have a winner.
                            newBucketSet.prevSet = currentBucketSet;
                        }

                        // Note that at this point we don't update currentBucketSet.  On the next loop
                        // iteration we should be able to pick up where we left off.
                    }
                    else
                    {
                        lastBucketSet    = currentBucketSet;
                        currentBucketSet = nextBucketSet;
                    }
                }while (currentBucketSet.AbsoluteTimeout > txNew.AbsoluteTimeout);

                if (currentBucketSet.AbsoluteTimeout != txNew.AbsoluteTimeout)
                {
                    //
                    // Getting to here means that we've found a slot in the list where this bucket set should go.
                    //
                    BucketSet     newBucketSet = new BucketSet(this, txNew.AbsoluteTimeout);
                    WeakReference newSetWeak   = new WeakReference(newBucketSet);

                    newBucketSet.nextSetWeak = lastBucketSet.nextSetWeak;
                    WeakReference oldNextSetWeak = (WeakReference)Interlocked.CompareExchange(
                        ref lastBucketSet.nextSetWeak, newSetWeak, newBucketSet.nextSetWeak);
                    if (oldNextSetWeak == newBucketSet.nextSetWeak)
                    {
                        // Ladies and Gentlemen we have a winner.
                        if (oldNextSetWeak != null)
                        {
                            BucketSet oldSet = (BucketSet)oldNextSetWeak.Target;
                            if (oldSet != null)
                            {
                                // prev references are just there to root things for the GC.  If this object is
                                // gone we don't really care.
                                oldSet.prevSet = newBucketSet;
                            }
                        }
                        newBucketSet.prevSet = lastBucketSet;
                    }

                    // Special note - We are going to loop back to the BucketSet that preceeds the one we just tried
                    // to insert because we may have lost the race to insert our new BucketSet into the list to another
                    // "Add" thread. By looping back, we check again to see if the BucketSet we just created actually
                    // got added. If it did, we will exit out of the outer loop and add the transaction. But if we
                    // lost the race, we will again try to add a new BucketSet. In the latter case, the BucketSet
                    // we created during the first iteration will simply be Garbage Collected because there are no
                    // strong references to it since we never added the transaction to a bucket and the act of
                    // creating the second BucketSet with remove the backward reference that was created in the
                    // first trip thru the loop.
                    currentBucketSet = lastBucketSet;
                    lastBucketSet    = null;

                    // The outer loop will iterate and pick up where we left off.
                }
            }

            //
            // Great we found a spot.
            //
            currentBucketSet.Add(txNew);
        }
 private void ThreadTimer(object state)
 {
     if (!this.timerEnabled)
     {
         return;
     }
     this.ticks += 1L;
     this.lastTimerTime = DateTime.UtcNow.Ticks;
     BucketSet set4 = null;
     BucketSet headBucketSet = this.headBucketSet;
     WeakReference nextSetWeak = (WeakReference) headBucketSet.nextSetWeak;
     BucketSet target = null;
     if (nextSetWeak != null)
     {
         target = (BucketSet) nextSetWeak.Target;
     }
     if (target == null)
     {
         this.rwLock.AcquireWriterLock();
         try
         {
             if (!this.timer.Change(-1, -1))
             {
                 throw TransactionException.CreateInvalidOperationException(System.Transactions.SR.GetString("TraceSourceLtm"), System.Transactions.SR.GetString("UnexpectedTimerFailure"), null);
             }
             this.timerEnabled = false;
             return;
         }
         finally
         {
             this.rwLock.ReleaseWriterLock();
         }
     }
 Label_00A0:
     nextSetWeak = (WeakReference) headBucketSet.nextSetWeak;
     if (nextSetWeak != null)
     {
         target = (BucketSet) nextSetWeak.Target;
         if (target != null)
         {
             set4 = headBucketSet;
             headBucketSet = target;
             if (headBucketSet.AbsoluteTimeout <= this.ticks)
             {
                 Thread.BeginCriticalRegion();
                 try
                 {
                     WeakReference reference2 = (WeakReference) Interlocked.CompareExchange(ref set4.nextSetWeak, null, nextSetWeak);
                     if (reference2 == nextSetWeak)
                     {
                         BucketSet set = null;
                         do
                         {
                             if (reference2 != null)
                             {
                                 set = (BucketSet) reference2.Target;
                             }
                             else
                             {
                                 set = null;
                             }
                             if (set != null)
                             {
                                 set.TimeoutTransactions();
                                 reference2 = (WeakReference) set.nextSetWeak;
                             }
                         }
                         while (set != null);
                         return;
                     }
                 }
                 finally
                 {
                     Thread.EndCriticalRegion();
                 }
                 headBucketSet = set4;
             }
             goto Label_00A0;
         }
     }
 }
Example #11
0
        private void ThreadTimer(object state)
        {
            if (!this.timerEnabled)
            {
                return;
            }
            this.ticks        += 1L;
            this.lastTimerTime = DateTime.UtcNow.Ticks;
            BucketSet     set4          = null;
            BucketSet     headBucketSet = this.headBucketSet;
            WeakReference nextSetWeak   = (WeakReference)headBucketSet.nextSetWeak;
            BucketSet     target        = null;

            if (nextSetWeak != null)
            {
                target = (BucketSet)nextSetWeak.Target;
            }
            if (target == null)
            {
                this.rwLock.AcquireWriterLock();
                try
                {
                    if (!this.timer.Change(-1, -1))
                    {
                        throw TransactionException.CreateInvalidOperationException(System.Transactions.SR.GetString("TraceSourceLtm"), System.Transactions.SR.GetString("UnexpectedTimerFailure"), null);
                    }
                    this.timerEnabled = false;
                    return;
                }
                finally
                {
                    this.rwLock.ReleaseWriterLock();
                }
            }
Label_00A0:
            nextSetWeak = (WeakReference)headBucketSet.nextSetWeak;
            if (nextSetWeak != null)
            {
                target = (BucketSet)nextSetWeak.Target;
                if (target != null)
                {
                    set4          = headBucketSet;
                    headBucketSet = target;
                    if (headBucketSet.AbsoluteTimeout <= this.ticks)
                    {
                        Thread.BeginCriticalRegion();
                        try
                        {
                            WeakReference reference2 = (WeakReference)Interlocked.CompareExchange(ref set4.nextSetWeak, null, nextSetWeak);
                            if (reference2 == nextSetWeak)
                            {
                                BucketSet set = null;
                                do
                                {
                                    if (reference2 != null)
                                    {
                                        set = (BucketSet)reference2.Target;
                                    }
                                    else
                                    {
                                        set = null;
                                    }
                                    if (set != null)
                                    {
                                        set.TimeoutTransactions();
                                        reference2 = (WeakReference)set.nextSetWeak;
                                    }
                                }while (set != null);
                                return;
                            }
                        }
                        finally
                        {
                            Thread.EndCriticalRegion();
                        }
                        headBucketSet = set4;
                    }
                    goto Label_00A0;
                }
            }
        }
Example #12
0
        void AddIter( InternalTransaction txNew )
        {
            //
            // Theory of operation.
            //
            // Note that the head bucket contains any transaction with essentially infinite
            // timeout (long.MaxValue).  The list is sorted in decending order.  To add
            // a node the code must walk down the list looking for a set of bucket that matches
            // the absolute timeout value for the transaction.  When it is found it passes
            // the insert down to that set.
            //
            // An importent thing to note about the list is that forward links are all weak
            // references and reverse links are all strong references.  This allows the GC
            // to clean up old links in the list so that they don't need to be removed manually.
            // However if there is still a rooted strong reference to an old link in the
            // chain that link wont fall off the list because there is a strong reference held
            // forward.
            //
            
            BucketSet currentBucketSet = this.headBucketSet;

            while ( currentBucketSet.AbsoluteTimeout != txNew.AbsoluteTimeout )
            {
                BucketSet lastBucketSet = null;
                do
                {
                    WeakReference nextSetWeak = (WeakReference)currentBucketSet.nextSetWeak;
                    BucketSet nextBucketSet = null;
                    if ( nextSetWeak != null )
                    {
                        nextBucketSet = (BucketSet)nextSetWeak.Target;
                    }
                    
                    if ( nextBucketSet == null )
                    {
                        //
                        // We've reached the end of the list either because nextSetWeak was null or
                        // because its reference was collected.  This code doesn't care.  Make a new
                        // set, attempt to attach it and move on.
                        //
                        BucketSet newBucketSet = new BucketSet( this, txNew.AbsoluteTimeout );
                        WeakReference newSetWeak = new WeakReference( newBucketSet );

                        WeakReference oldNextSetWeak = (WeakReference)Interlocked.CompareExchange( 
                            ref currentBucketSet.nextSetWeak, newSetWeak, nextSetWeak );
                        if ( oldNextSetWeak == nextSetWeak )
                        {
                            // Ladies and Gentlemen we have a winner.
                            newBucketSet.prevSet = currentBucketSet;
                        }

                        // Note that at this point we don't update currentBucketSet.  On the next loop
                        // iteration we should be able to pick up where we left off.
                    }
                    else
                    {
                        lastBucketSet = currentBucketSet;
                        currentBucketSet = nextBucketSet;
                    }
                }
                while ( currentBucketSet.AbsoluteTimeout > txNew.AbsoluteTimeout );

                if ( currentBucketSet.AbsoluteTimeout != txNew.AbsoluteTimeout )
                {
                    //
                    // Getting to here means that we've found a slot in the list where this bucket set should go.
                    //
                    BucketSet newBucketSet = new BucketSet( this, txNew.AbsoluteTimeout );
                    WeakReference newSetWeak = new WeakReference( newBucketSet );

                    newBucketSet.nextSetWeak = lastBucketSet.nextSetWeak;
                    WeakReference oldNextSetWeak = (WeakReference)Interlocked.CompareExchange( 
                        ref lastBucketSet.nextSetWeak, newSetWeak, newBucketSet.nextSetWeak );
                    if ( oldNextSetWeak == newBucketSet.nextSetWeak )
                    {
                        // Ladies and Gentlemen we have a winner.
                        if ( oldNextSetWeak != null )
                        {
                            BucketSet oldSet = (BucketSet)oldNextSetWeak.Target;
                            if ( oldSet != null )
                            {
                                // prev references are just there to root things for the GC.  If this object is 
                                // gone we don't really care.
                                oldSet.prevSet = newBucketSet;
                            }
                        }
                        newBucketSet.prevSet = lastBucketSet;
                    }

                    // Special note - We are going to loop back to the BucketSet that preceeds the one we just tried
                    // to insert because we may have lost the ---- to insert our new BucketSet into the list to another
                    // "Add" thread. By looping back, we check again to see if the BucketSet we just created actually
                    // got added. If it did, we will exit out of the outer loop and add the transaction. But if we
                    // lost the ----, we will again try to add a new BucketSet. In the latter case, the BucketSet
                    // we created during the first iteration will simply be Garbage Collected because there are no
                    // strong references to it since we never added the transaction to a bucket and the act of
                    // creating the second BucketSet with remove the backward reference that was created in the
                    // first trip thru the loop.
                    currentBucketSet = lastBucketSet;
                    lastBucketSet = null;

                    // The outer loop will iterate and pick up where we left off.
                }
            }

            //
            // Great we found a spot.
            //
            currentBucketSet.Add( txNew );
        }
Example #13
0
        internal TransactionTable()
        {
            // Create a timer that is initially disabled by specifing an Infinite time to the first interval
            this.timer = new Timer( new TimerCallback(ThreadTimer), null, Timeout.Infinite, this.timerInterval );

            // Note that the timer is disabled
            this.timerEnabled = false;

            // Store the timer interval
            this.timerInterval = 1 << TransactionTable.timerInternalExponent;

            // Ticks start off at zero.
            this.ticks = 0;

            // The head of the list is long.MaxValue.  It contains all of the transactions that for
            // some reason or other don't have a timeout.
            this.headBucketSet = new BucketSet( this, long.MaxValue );

            // Allocate the lock
            rwLock = new CheapUnfairReaderWriterLock();
        }
Example #14
0
 internal Bucket(BucketSet owningSet)
 {
     this.transactions = new InternalTransaction[this.size];
     this.owningSet    = owningSet;
 }
 internal Bucket(BucketSet owningSet)
 {
     this.transactions = new InternalTransaction[this.size];
     this.owningSet = owningSet;
 }