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); }
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); }