Пример #1
0
 /// <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++;
 }
Пример #2
0
 /// <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);
 }
Пример #3
0
        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);
        }