/// <summary> /// Removes all the elements. /// </summary> public void Clear() { _entriesOld = null; _entriesNew = new FixedSizeQueueBucket <T>(INT_DefaultCapacity); Thread.VolatileWrite(ref _status, (int)BucketStatus.Free); Thread.VolatileWrite(ref _count, 0); _revision++; }
/// <summary> /// Initializes a new instance of the <see cref="QueueBucket{T}" /> class. /// </summary> /// <param name="initialCapacity">The initial capacity.</param> public QueueBucket(int initialCapacity) { _entriesOld = null; _entriesNew = new FixedSizeQueueBucket <T>(initialCapacity); }
private void CooperativeGrow() { int status; do { status = Thread.VolatileRead(ref _status); int oldStatus; switch (status) { case (int)BucketStatus.GrowRequested: var priority = Thread.CurrentThread.Priority; oldStatus = Interlocked.CompareExchange(ref _status, (int)BucketStatus.Waiting, (int)BucketStatus.GrowRequested); if (oldStatus == (int)BucketStatus.GrowRequested) { try { Thread.CurrentThread.Priority = ThreadPriority.Highest; Thread.VolatileWrite(ref _copySourcePosition, -1); var newCapacity = _entriesNew.Capacity * 2; _entriesOld = Interlocked.Exchange(ref _entriesNew, new FixedSizeQueueBucket <T>(newCapacity)); oldStatus = Interlocked.CompareExchange(ref _status, (int)BucketStatus.Copy, (int)BucketStatus.Waiting); } finally { Thread.CurrentThread.Priority = priority; _revision++; } } break; case (int)BucketStatus.Waiting: Thread.SpinWait(INT_SpinWaitHint); if (Thread.VolatileRead(ref _status) == 2) { Thread.Sleep(0); } break; case (int)BucketStatus.Copy: _revision++; if (Thread.VolatileRead(ref _workingThreads) > 0) { Thread.SpinWait(INT_SpinWaitHint); while (Thread.VolatileRead(ref _workingThreads) > 0) { Thread.Sleep(0); Thread.SpinWait(INT_SpinWaitHint); } } var old = _entriesOld; if (old != null) { _revision++; Interlocked.Increment(ref _copyingThreads); T item; int capacity = old.Capacity; int offset = old.IndexDequeue; int sourceIndex = Interlocked.Increment(ref _copySourcePosition); while (sourceIndex < capacity) { if (old.TryGet((sourceIndex + offset) & (capacity - 1), out item)) { //HACK bool dummy; _entriesNew.Set(sourceIndex, item, out dummy); } sourceIndex = Interlocked.Increment(ref _copySourcePosition); } Interlocked.CompareExchange(ref _status, (int)BucketStatus.Waiting, (int)BucketStatus.Copy); _revision++; if (Interlocked.Decrement(ref _copyingThreads) == 0) { //HACK _entriesNew.IndexEnqueue = capacity; Interlocked.CompareExchange(ref _status, (int)BucketStatus.CopyCleanup, (int)BucketStatus.Waiting); } } break; case (int)BucketStatus.CopyCleanup: oldStatus = Interlocked.CompareExchange(ref _status, (int)BucketStatus.Waiting, 4); if (oldStatus == (int)BucketStatus.CopyCleanup) { _revision++; Interlocked.Exchange(ref _entriesOld, null); Thread.Sleep(1); Interlocked.CompareExchange(ref _status, (int)BucketStatus.Free, (int)BucketStatus.Waiting); } break; default: break; } }while (status != (int)BucketStatus.Waiting); }