示例#1
0
        public void Release()
        {
            Waiter toFinish = null;

            lock (_lock)
            {
                if (currentPermits + 1 > maxPermits)
                {
                    throw new ArgumentOutOfRangeException("releases");
                }
                currentPermits += 1;
                Waiter waiter;
                while ((waiter = (Waiter)DListNode.FirstEntry(waiters)) != null)
                {
                    if (Volatile.Read(ref waiter.state) != WAITING)
                    {
                        DListNode.RemoveIfInserted(waiter);
                        continue;
                    }
                    if (waiter.TrySetState(SUCCESS))
                    {
                        DListNode.RemoveIfInserted(waiter);
                        currentPermits -= 1;
                        toFinish        = waiter;
                        break;
                    }
                }
            }
            // finish it outside the lock
            if (toFinish != null)
            {
                // cancel the active cancelers
                if (toFinish.ctkReg != null)
                {
                    toFinish.ctkReg.Dispose();
                }
                if (toFinish.timer != null)
                {
                    toFinish.timer.Dispose();
                }
                toFinish.tcs.SetResult(true);
            }
        }
示例#2
0
        public void Release()
        {
            Waiter <Data> toFinish = null;

            lock (_lock)
            {
                if (currentPermits + 1 > maxPermits)
                {
                    throw new ArgumentOutOfRangeException("releases");
                }
                currentPermits += 1;
                Waiter <Data> waiter;
                while ((waiter = (Waiter <Data>)DListNode.FirstEntry(waiters)) != null)
                {
                    if (Volatile.Read(ref waiter.state) != WaiterState.WAITING)
                    {
                        // Shouldn't already be on the queue, ensure it is removed
                        DListNode.RemoveIfInserted(waiter);
                        continue;
                    }
                    if (waiter.TrySetStateAndUnlink(WaiterState.SUCCESS))
                    {
                        currentPermits -= 1;
                        // queue node for further processing outside the lock
                        waiter.prev = toFinish;
                        toFinish    = waiter;
                        break;
                    }
                }
            }
            // finish the stack of satisfied requests
            while (toFinish != null)
            {
                toFinish.OnSuccess();
                toFinish = (Waiter <Data>)toFinish.prev;
            }
        }