public void Enqueue(T item)
        {
            if (_size >= _items.Length)
            {
                var temp = _items;
                _items = new IndexedItem[_items.Length * 2];
                Array.Copy(temp, _items, temp.Length);
            }

            var index = _size++;

            _items[index] = new IndexedItem {
                Value = item, Id = Interlocked2.Increment(ref _count)
            };
            Percolate(index);
        }
        private static void MultipleProducerConsumer_AllItemsTransferred(int producers, int consumers, int itemsPerProducer)
        {
            var cq    = new ConcurrentQueue <int>();
            var tasks = new List <Task>();

            int totalItems     = producers * itemsPerProducer;
            int remainingItems = totalItems;
            int sum            = 0;

            for (int i = 0; i < consumers; i++)
            {
                tasks.Add(Task.Factory.StartNew(() =>
                {
                    while (Volatile.Read(ref remainingItems) > 0)
                    {
                        int item;
                        if (cq.TryDequeue(out item))
                        {
                            Interlocked2.Add(ref sum, item);
                            Interlocked.Decrement(ref remainingItems);
                        }
                    }
                }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default));
            }

            for (int i = 0; i < producers; i++)
            {
                tasks.Add(Task.Factory.StartNew(() =>
                {
                    for (int item = 1; item <= itemsPerProducer; item++)
                    {
                        cq.Enqueue(item);
                    }
                }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default));
            }

            Task.WaitAll(tasks.ToArray());

            Assert.AreEqual(producers * (itemsPerProducer * (itemsPerProducer + 1) / 2), sum);
        }
示例#3
0
        /// <summary>
        /// Acquires the lock in shared mode, blocking
        /// if necessary.
        /// </summary>
        /// <remarks>
        /// Exclusive acquires are given precedence over shared
        /// acquires.
        /// </remarks>
        public void AcquireShared()
        {
            int value;
            int i = 0;

#if ENABLE_STATISTICS
            Interlocked.Increment(ref _acqShrdCount);
#endif
            while (true)
            {
                value = _value;

                // Case 1: lock not owned AND no exclusive waiter is waking up AND
                // there are no shared owners AND there are no exclusive waiters
                if ((value & (
                         LockOwned |
                         (LockSharedOwnersMask << LockSharedOwnersShift) |
                         ExclusiveMask
                         )) == 0)
                {
                    if (Interlocked.CompareExchange(
                            ref _value,
                            value + LockOwned + LockSharedOwnersIncrement,
                            value
                            ) == value)
                    {
                        break;
                    }
                }
                // Case 2: lock is owned AND no exclusive waiter is waking up AND
                // there are shared owners AND there are no exclusive waiters
                else if (
                    (value & LockOwned) != 0 &&
                    ((value >> LockSharedOwnersShift) & LockSharedOwnersMask) != 0 &&
                    (value & ExclusiveMask) == 0
                    )
                {
                    if (Interlocked.CompareExchange(
                            ref _value,
                            value + LockSharedOwnersIncrement,
                            value
                            ) == value)
                    {
                        break;
                    }
                }
                // Other cases.
                else if (i >= SpinCount)
                {
#if DEFER_EVENT_CREATION
                    this.EnsureEventCreated(ref _sharedWakeEvent);
#endif
                    if (Interlocked.CompareExchange(
                            ref _value,
                            value + LockSharedWaitersIncrement,
                            value
                            ) == value)
                    {
#if ENABLE_STATISTICS
                        Interlocked.Increment(ref _acqShrdSlpCount);

                        int shrdWtrsCount = (value >> LockSharedWaitersShift) & LockSharedWaitersMask;

                        Interlocked2.Set(
                            ref _peakShrdWtrsCount,
                            (p) => p < shrdWtrsCount,
                            (p) => shrdWtrsCount
                            );
#endif
                        // Go to sleep.
                        if (NativeMethods.WaitForSingleObject(
                                _sharedWakeEvent,
                                Timeout.Infinite
                                ) != NativeMethods.WaitObject0)
                        {
                            UtilsBreak("Utils.MsgFailedToWaitIndefinitely");
                        }

                        // Go back and try again.
                        continue;
                    }
                }

#if ENABLE_STATISTICS
                Interlocked.Increment(ref _acqShrdContCount);
#endif
                i++;
            }
        }
示例#4
0
        /// <summary>
        /// Acquires the lock in exclusive mode, blocking
        /// if necessary.
        /// </summary>
        /// <remarks>
        /// Exclusive acquires are given precedence over shared
        /// acquires.
        /// </remarks>
        public void AcquireExclusive()
        {
            int value;
            int i = 0;

#if ENABLE_STATISTICS
            Interlocked.Increment(ref _acqExclCount);
#endif
            while (true)
            {
                value = _value;

                // Case 1: lock not owned AND an exclusive waiter is not waking up.
                // Here we don't have to check if there are exclusive waiters, because
                // if there are the lock would be owned, and we are checking that anyway.
                if ((value & (LockOwned | LockExclusiveWaking)) == 0)
                {
#if RIGOROUS_CHECKS
                    System.Diagnostics.Trace.Assert(((value >> LockSharedOwnersShift) & LockSharedOwnersMask) == 0);
                    System.Diagnostics.Trace.Assert(((value >> LockExclusiveWaitersShift) & LockExclusiveWaitersMask) == 0);
#endif
                    if (Interlocked.CompareExchange(
                            ref _value,
                            value + LockOwned,
                            value
                            ) == value)
                    {
                        break;
                    }
                }
                // Case 2: lock owned OR lock not owned and an exclusive waiter is waking up.
                // The second case means an exclusive waiter has just been woken up and is
                // going to acquire the lock. We have to go to sleep to make sure we don't
                // steal the lock.
                else if (i >= SpinCount)
                {
#if DEFER_EVENT_CREATION
                    // This call must go *before* the next operation. Otherwise,
                    // we will have a race condition between potential releasers
                    // and us.
                    this.EnsureEventCreated(ref _exclusiveWakeEvent);
#endif
                    if (Interlocked.CompareExchange(
                            ref _value,
                            value + LockExclusiveWaitersIncrement,
                            value
                            ) == value)
                    {
#if ENABLE_STATISTICS
                        Interlocked.Increment(ref _acqExclSlpCount);

                        int exclWtrsCount = (value >> LockExclusiveWaitersShift) & LockExclusiveWaitersMask;

                        Interlocked2.Set(
                            ref _peakExclWtrsCount,
                            (p) => p < exclWtrsCount,
                            (p) => exclWtrsCount
                            );
#endif
                        // Go to sleep.
                        if (NativeMethods.WaitForSingleObject(
                                _exclusiveWakeEvent,
                                Timeout.Infinite
                                ) != NativeMethods.WaitObject0)
                        {
                            UtilsBreak("Utils.MsgFailedToWaitIndefinitely");
                        }

                        // Acquire the lock.
                        // At this point *no one* should be able to steal the lock from us.
                        do
                        {
                            value = _value;
#if RIGOROUS_CHECKS
                            System.Diagnostics.Trace.Assert((value & LockOwned) == 0);
                            System.Diagnostics.Trace.Assert((value & LockExclusiveWaking) != 0);
#endif
                        } while(Interlocked.CompareExchange(
                                    ref _value,
                                    value + LockOwned - LockExclusiveWaking,
                                    value
                                    ) != value);

                        break;
                    }
                }

#if ENABLE_STATISTICS
                Interlocked.Increment(ref _acqExclContCount);
#endif
                i++;
            }
        }