public void Release <T>(T value) where T : class { Contract.Requires(value == this.Value, "value differs from one backed by this handle."); Stack stack = this.Stack; Thread thread = Thread.CurrentThread; if (stack.Thread == thread) { stack.Push(this); return; } ConditionalWeakTable <Stack, WeakOrderQueue> queueDictionary = DelayedPool.Value; WeakOrderQueue delayedRecycled; if (!queueDictionary.TryGetValue(stack, out delayedRecycled)) { var newQueue = new WeakOrderQueue(stack, thread); delayedRecycled = newQueue; queueDictionary.Add(stack, delayedRecycled); } delayedRecycled.Add(this); }
internal WeakOrderQueue(Stack stack, Thread thread) { Contract.Requires(stack != null); this.ownerThread = new WeakReference <Thread>(thread); this.head = this.tail = new Link(); lock (stack) { this.next = stack.HeadQueue; stack.HeadQueue = this; } }
bool Scavenge() { // continue an existing scavenge, if any if (this.ScavengeSome()) { return(true); } // reset our scavenge cursor this.prevQueue = null; this.cursorQueue = this.HeadQueue; return(false); }
bool ScavengeSome() { WeakOrderQueue cursor = this.cursorQueue; if (cursor == null) { cursor = this.HeadQueue; if (cursor == null) { return(false); } } bool success = false; WeakOrderQueue prev = this.prevQueue; do { if (cursor.Transfer(this)) { success = true; break; } WeakOrderQueue next = cursor.next; Thread ownerThread; if (!cursor.ownerThread.TryGetTarget(out ownerThread)) { // If the thread associated with the queue is gone, unlink it, after // performing a volatile read to confirm there is no data left to collect. // We never unlink the first queue, as we don't want to synchronize on updating the head. if (!cursor.IsEmpty) { for (;;) { if (cursor.Transfer(this)) { success = true; } else { break; } } } if (prev != null) { prev.next = next; } } else { prev = cursor; } cursor = next; }while (cursor != null && !success); this.prevQueue = prev; this.cursorQueue = cursor; return(success); }