public virtual void DoWait(IQueuedSync sync)
 {
     lock (this)
     {
         if (!sync.Recheck(this))
         {
             try
             {
                 while (_waiting)
                 {
                     Monitor.Wait(this);
                 }
             }
             catch (ThreadInterruptedException ex)
             {
                 if (_waiting)
                 {
                     // no notification
                     _waiting = false;                             // invalidate for the signaller
                     throw SystemExtensions.PreserveStackTrace(ex);
                 }
                 // thread was interrupted after it was notified
                 Thread.CurrentThread.Interrupt();
                 return;
             }
         }
     }
 }
        /// <summary>
        /// Retrieves and removes the head of this queue, waiting up to the
        /// specified wait time if necessary for an element to become available.
        /// </summary>
        /// <param name="element">
        /// Set to the head of this queue. <c>default(T)</c> if queue is empty.
        /// </param>
        /// <param name="duration">How long to wait before giving up.</param>
        /// <returns>
        /// <c>false</c> if the queue is still empty after waited for the time
        /// specified by the <paramref name="duration"/>. Otherwise <c>true</c>.
        /// </returns>
        public override bool Poll(TimeSpan duration, out T element)
        {
            DateTime deadline = WaitTime.Deadline(duration);

            using (_lock.LockInterruptibly())
            {
                while (!_wrapped.Poll(out element))
                {
                    if (duration.Ticks <= 0)
                    {
                        element = default(T);
                        return(false);
                    }
                    try
                    {
                        _notEmptyCondition.Await(WaitTime.Cap(duration));
                        duration = deadline.Subtract(DateTime.UtcNow);
                    }
                    catch (ThreadInterruptedException e)
                    {
                        _notEmptyCondition.Signal();
                        throw SystemExtensions.PreserveStackTrace(e);
                    }
                }
                _notFullCondition.Signal();
                return(true);
            }
        }
            public override void LockInterruptibly()
            {
                Thread caller = Thread.CurrentThread;

                lock (this)
                {
                    if (GetHold(caller))
                    {
                        return;
                    }
                    try
                    {
                        do
                        {
                            Monitor.Wait(this);
                        } while (_owner != null);
                        _owner = caller;
                        _holds = 1;
                        return;
                    }
                    catch (ThreadInterruptedException e)
                    {
                        if (_owner == null)
                        {
                            Monitor.Pulse(this);
                        }
                        throw SystemExtensions.PreserveStackTrace(e);
                    }
                }
            }
Exemplo n.º 4
0
 /**
  * Tries to cancel on interrupt; if so rethrowing,
  * else setting interrupt state
  *
  * PRE: lock owned
  */
 private void CheckCancellationOnInterrupt(ThreadInterruptedException ie)
 {
     if (_state == 0)
     {
         _state = Cancel;
         Monitor.Pulse(this);
         throw SystemExtensions.PreserveStackTrace(ie);
     }
     Thread.CurrentThread.Interrupt();
 }
        public virtual bool AwaitUntil(DateTime deadline)
        {
            int holdCount = _lock.HoldCount;

            if (holdCount == 0)
            {
                throw new SynchronizationLockException();
            }
            if ((deadline.Subtract(DateTime.UtcNow)).Ticks <= 0)
            {
                return(false);
            }
            // This requires sleep(0) to implement in .Net, too expensive!
            // if (Thread.interrupted()) throw new InterruptedException();
            try
            {
                lock (this)
                {
                    for (int i = holdCount; i > 0; i--)
                    {
                        _lock.Unlock();
                    }
                    try
                    {
                        // .Net has DateTime precision issue so we need to retry.
                        TimeSpan durationToWait;
                        while ((durationToWait = deadline.Subtract(DateTime.UtcNow)).Ticks > 0)
                        {
                            // .Net implementation is different than backport 3.1
                            // by taking advantage of the return value from Monitor.Wait.
                            if (Monitor.Wait(this, durationToWait))
                            {
                                return(true);
                            }
                        }
                    }
                    catch (ThreadInterruptedException e)
                    {
                        Monitor.Pulse(this);
                        throw SystemExtensions.PreserveStackTrace(e);
                    }
                }
            }
            finally
            {
                for (int i = holdCount; i > 0; i--)
                {
                    _lock.Lock();
                }
            }
            return(false);
        }
        /// <summary>
        /// Inserts the specified element into this queue, waiting if necessary
        /// for space to become available.
        /// </summary>
        /// <remarks>
        /// <see cref="Break"/> the queue will cause a waiting <see cref="TryPut"/>
        /// to returned <c>false</c>. This is very useful to indicate that the
        /// consumer is stopped or going to stop so that the producer should not
        /// put more items into the queue.
        /// </remarks>
        /// <param name="element">the element to add</param>
        /// <returns>
        /// <c>true</c> if succesfully and <c>false</c> if queue <see cref="IsBroken"/>.
        /// </returns>
        /// <exception cref="ThreadInterruptedException">
        /// if interrupted while waiting.
        /// </exception>
        public virtual bool TryPut(T element)
        {
            int tempCount;

            lock (_putLock)
            {
                /*
                 * Note that count is used in wait guard even though it is
                 * not protected by lock. This works because count can
                 * only decrease at this point (all other puts are shut
                 * out by lock), and we (or some other waiting put) are
                 * signaled if it ever changes from capacity. Similarly
                 * for all other uses of count in other wait guards.
                 */
                if (_isBroken)
                {
                    return(false);
                }
                try
                {
                    while (_activeCount == _capacity)
                    {
                        Monitor.Wait(_putLock);
                        if (_isBroken)
                        {
                            return(false);
                        }
                    }
                }
                catch (ThreadInterruptedException e) {
                    Monitor.Pulse(_putLock);
                    throw SystemExtensions.PreserveStackTrace(e);
                }
                Insert(element);
                lock (this) {
                    tempCount = _activeCount++;
                }
                if (tempCount + 1 < _capacity)
                {
                    Monitor.Pulse(_putLock);
                }
            }

            if (tempCount == 0)
            {
                SignalNotEmpty();
            }
            return(true);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Retrieves and removes the head of this queue, waiting up to the
        /// specified wait time if necessary for another thread to insert it.
        /// </summary>
        /// <param name="element">
        /// Set to the head of this queue. <c>default(T)</c> if queue is empty.
        /// </param>
        /// <param name="duration">How long to wait before giving up.</param>
        /// <returns>
        /// <c>false</c> if the queue is still empty after waited for the time
        /// specified by the <paramref name="duration"/>. Otherwise <c>true</c>.
        /// </returns>
        public override bool Poll(TimeSpan duration, out T element)
        {
            for (; ;)
            {
                Node node;
                bool mustWait;

                //if (Thread.interrupted()) throw new InterruptedException();
                using (_qlock.Lock())
                {
                    node     = _waitingProducers.Dequeue();
                    mustWait = (node == null);
                    if (mustWait)
                    {
                        node = _waitingConsumers.Enqueue(default(T));
                    }
                }

                if (mustWait)
                {
                    try {
                        T    x;
                        bool success = node.WaitForPut(duration, out x);
                        if (!success)
                        {
                            UnlinkCancelledConsumer(node);
                        }
                        element = x;
                        return(success);
                    }
                    catch (ThreadInterruptedException e) {
                        UnlinkCancelledConsumer(node);
                        throw SystemExtensions.PreserveStackTrace(e);
                    }
                }
                else
                {
                    T x;
                    if (node.GetItem(out x))
                    {
                        element = x;
                        return(true);
                    }
                    // else cancelled, so retry
                }
            }
        }
 public virtual bool DoTimedWait(IQueuedSync sync, TimeSpan duration)
 {
     lock (this)
     {
         if (sync.Recheck(this) || !_waiting)
         {
             return(true);
         }
         if (duration.Ticks <= 0)
         {
             _waiting = false;
             return(false);
         }
         DateTime deadline = DateTime.UtcNow.Add(duration);
         try
         {
             for (;;)
             {
                 Monitor.Wait(this, duration);
                 if (!_waiting)             // definitely signalled
                 {
                     return(true);
                 }
                 duration = deadline.Subtract(DateTime.UtcNow);
                 if (duration.Ticks <= 0)             // time out
                 {
                     _waiting = false;
                     return(false);
                 }
             }
         }
         catch (ThreadInterruptedException ex)
         {
             if (_waiting)             // no notification
             {
                 _waiting = false;     // invalidate for the signaller
                 throw SystemExtensions.PreserveStackTrace(ex);
             }
             // thread was interrupted after it was notified
             Thread.CurrentThread.Interrupt();
             return(true);
         }
     }
 }
        /// <summary>
        /// Inserts the specified element into this queue, waiting up to the
        /// specified wait time if necessary for space to become available.
        /// </summary>
        /// <param name="element">the element to add</param>
        /// <param name="duration">how long to wait before giving up</param>
        /// <returns> <c>true</c> if successful, or <c>false</c> if
        /// the specified waiting time elapses before space is available
        /// </returns>
        /// <exception cref="System.InvalidOperationException">
        /// If the element cannot be added at this time due to capacity restrictions.
        /// </exception>
        /// <exception cref="ThreadInterruptedException">
        /// if interrupted while waiting.
        /// </exception>
        public override bool Offer(T element, TimeSpan duration)
        {
            DateTime deadline = WaitTime.Deadline(duration);
            int      tempCount;

            lock (_putLock) {
                for (; ;)
                {
                    if (_isBroken)
                    {
                        return(false);
                    }
                    if (_activeCount < _capacity)
                    {
                        Insert(element);
                        lock (this) {
                            tempCount = _activeCount++;
                        }
                        if (tempCount + 1 < _capacity)
                        {
                            Monitor.Pulse(_putLock);
                        }
                        break;
                    }
                    if (duration.Ticks <= 0)
                    {
                        return(false);
                    }
                    try {
                        Monitor.Wait(_putLock, WaitTime.Cap(duration));
                        duration = deadline.Subtract(DateTime.UtcNow);
                    }
                    catch (ThreadInterruptedException e) {
                        Monitor.Pulse(_putLock);
                        throw SystemExtensions.PreserveStackTrace(e);
                    }
                }
            }
            if (tempCount == 0)
            {
                SignalNotEmpty();
            }
            return(true);
        }
        /// <summary>
        /// Retrieves and removes the head of this queue, waiting up to the
        /// specified wait time if necessary for an element to become available.
        /// </summary>
        /// <param name="element">
        /// Set to the head of this queue. <c>default(T)</c> if queue is empty.
        /// </param>
        /// <param name="duration">How long to wait before giving up.</param>
        /// <returns>
        /// <c>false</c> if the queue is still empty after waited for the time
        /// specified by the <paramref name="duration"/>. Otherwise <c>true</c>.
        /// </returns>
        public override bool Poll(TimeSpan duration, out T element)
        {
            DateTime deadline = WaitTime.Deadline(duration);
            T        x;
            int      c;

            lock (_takeLock) {
                for (; ;)
                {
                    if (_activeCount > 0)
                    {
                        x = Extract();
                        lock (this) {
                            c = _activeCount--;
                        }
                        if (c > 1)
                        {
                            Monitor.Pulse(_takeLock);
                        }
                        break;
                    }
                    if (duration.Ticks <= 0 || _isBroken)
                    {
                        element = default(T);
                        return(false);
                    }
                    try {
                        Monitor.Wait(_takeLock, WaitTime.Cap(duration));
                        duration = deadline.Subtract(DateTime.UtcNow);
                    }
                    catch (ThreadInterruptedException e) {
                        Monitor.Pulse(_takeLock);
                        throw SystemExtensions.PreserveStackTrace(e);
                    }
                }
            }
            if (c == _capacity)
            {
                SignalNotFull();
            }
            element = x;
            return(true);
        }
 /// <summary>
 /// Inserts the specified element into this queue, waiting if necessary
 /// for space to become available.
 /// </summary>
 /// <param name="element">the element to add</param>
 /// <exception cref="System.ArgumentNullException">
 /// If the specified element is <see langword="null"/> and this queue
 /// does not permit <see langword="null"/> elements.
 /// </exception>
 /// <exception cref="System.ArgumentException">
 /// If some property of the supplied <paramref name="element"/> prevents
 /// it from being added to this queue.
 /// </exception>
 public override void Put(T element)
 {
     using (_lock.LockInterruptibly())
     {
         try
         {
             while (!_wrapped.Offer(element))
             {
                 _notFullCondition.Await();
             }
             _notEmptyCondition.Signal();
         }
         catch (ThreadInterruptedException e)
         {
             _notFullCondition.Signal();
             throw SystemExtensions.PreserveStackTrace(e);
         }
     }
 }
            public override bool TryLock(TimeSpan durationToWait)
            {
                Thread caller = Thread.CurrentThread;

                lock (this)
                {
                    if (GetHold(caller))
                    {
                        return(true);
                    }
                    if (durationToWait.Ticks <= 0)
                    {
                        return(false);
                    }
                    DateTime deadline = DateTime.UtcNow.Add(durationToWait);
                    try
                    {
                        for (;;)
                        {
                            Monitor.Wait(this, durationToWait);
                            if (_owner == null)
                            {
                                _owner = caller;
                                _holds = 1;
                                return(true);
                            }
                            durationToWait = deadline.Subtract(DateTime.UtcNow);
                            if (durationToWait.Ticks <= 0)
                            {
                                return(false);
                            }
                        }
                    }
                    catch (ThreadInterruptedException e)
                    {
                        if (_owner == null)
                        {
                            Monitor.Pulse(this);
                        }
                        throw SystemExtensions.PreserveStackTrace(e);
                    }
                }
            }
Exemplo n.º 13
0
        /// <summary>
        /// Inserts the specified element into this queue, waiting up to the
        /// specified wait time if necessary for another thread to receive it.
        /// </summary>
        /// <param name="element">The element to add.</param>
        /// <param name="duration">How long to wait before giving up.</param>
        /// <returns>
        /// <see langword="true"/> if successful, or <see langword="false"/> if
        /// the specified waiting time elapses before space is available.
        /// </returns>
        /// <exception cref="ThreadInterruptedException">
        /// if interrupted while waiting.
        /// </exception>
        public override bool Offer(T element, TimeSpan duration)
        {
            for (; ;)
            {
                Node node;
                bool mustWait;
                //if (Thread.interrupted()) throw new InterruptedException();
                using (_qlock.Lock())
                {
                    node     = _waitingConsumers.Dequeue();
                    mustWait = (node == null);
                    if (mustWait)
                    {
                        node = _waitingProducers.Enqueue(element);
                    }
                }

                if (mustWait)
                {
                    try {
                        bool x = node.WaitForTake(duration);
                        if (!x)
                        {
                            UnlinkCancelledProducer(node);
                        }
                        return(x);
                    }
                    catch (ThreadInterruptedException tie) {
                        UnlinkCancelledProducer(node);
                        throw SystemExtensions.PreserveStackTrace(tie);
                    }
                }

                else if (node.SetItem(element))
                {
                    return(true);
                }

                // else consumer cancelled, so retry
            }
        }
 /// <summary>
 /// Retrieves and removes the head of this queue, waiting if necessary
 /// until an element becomes available.
 /// </summary>
 /// <returns> the head of this queue</returns>
 public override T Take()
 {
     using (_lock.LockInterruptibly())
     {
         try
         {
             T element;
             while (!_wrapped.Poll(out element))
             {
                 _notEmptyCondition.Await();
             }
             _notFullCondition.Signal();
             return(element);
         }
         catch (ThreadInterruptedException e)
         {
             _notEmptyCondition.Signal();
             throw SystemExtensions.PreserveStackTrace(e);
         }
     }
 }
        /// <summary>
        /// Retrieves and removes the head of this queue, waiting if necessary
        /// until an element becomes available.
        /// </summary>
        /// <remarks>
        /// <see cref="Break"/> the queue will cause a waiting <see cref="TryTake"/>
        /// to returned <c>false</c>. This is very useful to indicate that the
        /// producer is stopped so that the producer should stop waiting for
        /// element from queu.
        /// </remarks>
        /// <param name="element">
        /// The head of this queue if successful.
        /// </param>
        /// <returns>
        /// <c>true</c> if succesfully and <c>false</c> if queue is empty and
        /// <see cref="IsBroken">closed</see>.
        /// </returns>
        public virtual bool TryTake(out T element)
        {
            T   x;
            int tempCount;

            lock (_takeLock) {
                try {
                    while (_activeCount == 0)
                    {
                        if (_isBroken)
                        {
                            element = default(T);
                            return(false);
                        }
                        Monitor.Wait(_takeLock);
                    }
                }
                catch (ThreadInterruptedException e) {
                    Monitor.Pulse(_takeLock);
                    throw SystemExtensions.PreserveStackTrace(e);
                }

                x = Extract();
                lock (this) {
                    tempCount = _activeCount--;
                }
                if (tempCount > 1)
                {
                    Monitor.Pulse(_takeLock);
                }
            }
            if (tempCount == _capacity)
            {
                SignalNotFull();
            }

            element = x;
            return(true);
        }
Exemplo n.º 16
0
        /// <summary>
        /// Retrieves and removes the head of this queue, waiting if necessary
        /// until another thread inserts it.
        /// </summary>
        /// <returns> the head of this queue</returns>
        /// <exception cref="ThreadInterruptedException">
        /// if interrupted while waiting.
        /// </exception>
        public override T Take()
        {
            for (; ;)
            {
                Node node;
                bool mustWait;

                //if (Thread.interrupted()) throw new InterruptedException();
                using (_qlock.Lock())
                {
                    node     = _waitingProducers.Dequeue();
                    mustWait = (node == null);
                    if (mustWait)
                    {
                        node = _waitingConsumers.Enqueue(default(T));
                    }
                }

                if (mustWait)
                {
                    try {
                        return(node.WaitForPut());
                    }
                    catch (ThreadInterruptedException e) {
                        UnlinkCancelledConsumer(node);
                        throw SystemExtensions.PreserveStackTrace(e);
                    }
                }
                else
                {
                    T x;
                    if (node.GetItem(out x))
                    {
                        return(x);
                    }
                    // else cancelled, so retry
                }
            }
        }
        public virtual bool Await(TimeSpan durationToWait)
        {
            int holdCount = _lock.HoldCount;

            if (holdCount == 0)
            {
                throw new SynchronizationLockException();
            }
            // This requires sleep(0) to implement in .Net, too expensive!
            // if (Thread.interrupted()) throw new InterruptedException();
            try
            {
                lock (this)
                {
                    for (int i = holdCount; i > 0; i--)
                    {
                        _lock.Unlock();
                    }
                    try
                    {
                        // .Net implementation is a little different than backport 3.1
                        // by taking advantage of the return value from Monitor.Wait.
                        return((durationToWait.Ticks > 0) && Monitor.Wait(this, durationToWait));
                    }
                    catch (ThreadInterruptedException e)
                    {
                        Monitor.Pulse(this);
                        throw SystemExtensions.PreserveStackTrace(e);
                    }
                }
            }
            finally
            {
                for (int i = holdCount; i > 0; i--)
                {
                    _lock.Lock();
                }
            }
        }
        public virtual void Await()
        {
            int holdCount = _lock.HoldCount;

            if (holdCount == 0)
            {
                throw new SynchronizationLockException();
            }
            // This requires sleep(0) to implement in .Net, too expensive!
            // if (Thread.interrupted()) throw new InterruptedException();
            try
            {
                lock (this)
                {
                    for (int i = holdCount; i > 0; i--)
                    {
                        _lock.Unlock();
                    }
                    try
                    {
                        Monitor.Wait(this);
                    }
                    catch (ThreadInterruptedException e)
                    {
                        Monitor.Pulse(this);
                        throw SystemExtensions.PreserveStackTrace(e);
                    }
                }
            }
            finally
            {
                for (int i = holdCount; i > 0; i--)
                {
                    _lock.Lock();
                }
            }
        }
        /// <summary>
        /// <see cref="ITakable.Poll"/>
        /// </summary>
        public virtual Object Poll(long msecs)
        {
            long waitTime  = msecs;
            long startTime = 0;

            for (; ;)
            {
                Utils.FailFastIfInterrupted();
                LinkedNode item;
                LinkedNode slot = null;

                lock (this)
                {
                    item = waitingPuts.Deq();
                    if (item == null)
                    {
                        if (waitTime <= 0)
                        {
                            return(null);
                        }
                        else
                        {
                            waitingTakes.Enq(slot = new LinkedNode());
                        }
                    }
                }

                if (item != null)
                {
                    lock (item)
                    {
                        Object x = item.Value;
                        if (x != Cancelled)
                        {
                            item.Value = null;
                            item.Next  = null;
                            Monitor.Pulse(item);
                            return(x);
                        }
                    }
                }

                long now = Utils.CurrentTimeMillis;
                if (startTime == 0)
                {
                    startTime = now;
                }
                else
                {
                    waitTime = msecs - (now - startTime);
                }

                if (slot != null)
                {
                    lock (slot)
                    {
                        try
                        {
                            for (; ;)
                            {
                                Object x = slot.Value;
                                if (x != null)
                                {
                                    slot.Value = null;
                                    slot.Next  = null;
                                    return(x);
                                }
                                if (waitTime <= 0)
                                {
                                    slot.Value = Cancelled;
                                    return(null);
                                }
                                Monitor.Wait(slot, TimeSpan.FromMilliseconds(waitTime));
                                waitTime = msecs - (Utils.CurrentTimeMillis - startTime);
                            }
                        }
                        catch (ThreadInterruptedException ie)
                        {
                            Object x = slot.Value;
                            if (x != null)
                            {
                                slot.Value = null;
                                slot.Next  = null;
                                Thread.CurrentThread.Interrupt();
                                return(x);
                            }
                            else
                            {
                                slot.Value = Cancelled;
                                throw SystemExtensions.PreserveStackTrace(ie);
                            }
                        }
                    }
                }
            }
        }
        /*
         * Offer and poll are just like put and take, except even messier.
         */


        /// <summary>
        /// <see cref="IPuttable.Offer"/>
        /// </summary>
        public virtual bool Offer(Object x, long msecs)
        {
            if (x == null)
            {
                throw new ArgumentException();
            }
            long waitTime  = msecs;
            long startTime = 0; // lazily initialize below if needed

            for (; ;)
            {
                Utils.FailFastIfInterrupted();
                LinkedNode slot;
                LinkedNode item = null;

                lock (this)
                {
                    slot = waitingTakes.Deq();
                    if (slot == null)
                    {
                        if (waitTime <= 0)
                        {
                            return(false);
                        }
                        else
                        {
                            waitingPuts.Enq(item = new LinkedNode(x));
                        }
                    }
                }

                if (slot != null)
                {
                    lock (slot)
                    {
                        if (slot.Value != Cancelled)
                        {
                            slot.Value = x;
                            Monitor.Pulse(slot);
                            return(true);
                        }
                    }
                }

                long now = Utils.CurrentTimeMillis;
                if (startTime == 0)
                {
                    startTime = now;
                }
                else
                {
                    waitTime = msecs - (now - startTime);
                }

                if (item != null)
                {
                    lock (item)
                    {
                        try
                        {
                            for (; ;)
                            {
                                if (item.Value == null)
                                {
                                    return(true);
                                }
                                if (waitTime <= 0)
                                {
                                    item.Value = Cancelled;
                                    return(false);
                                }
                                Monitor.Wait(item, TimeSpan.FromMilliseconds(waitTime));
                                waitTime = msecs - (Utils.CurrentTimeMillis - startTime);
                            }
                        }
                        catch (ThreadInterruptedException ie)
                        {
                            if (item.Value == null)
                            {
                                Thread.CurrentThread.Interrupt();
                                return(true);
                            }
                            else
                            {
                                item.Value = Cancelled;
                                throw SystemExtensions.PreserveStackTrace(ie);
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// <see cref="ITakable.Take"/>
        /// </summary>
        public virtual Object Take()
        {
            // Entirely symmetric to put()

            for (; ;)
            {
                Utils.FailFastIfInterrupted();
                LinkedNode item;
                LinkedNode slot = null;

                lock (this)
                {
                    item = waitingPuts.Deq();
                    if (item == null)
                    {
                        waitingTakes.Enq(slot = new LinkedNode());
                    }
                }

                if (item != null)
                {
                    lock (item)
                    {
                        Object x = item.Value;
                        if (x != Cancelled)
                        {
                            item.Value = null;
                            item.Next  = null;
                            Monitor.Pulse(item);
                            return(x);
                        }
                    }
                }
                else
                {
                    lock (slot)
                    {
                        try
                        {
                            for (; ;)
                            {
                                Object x = slot.Value;
                                if (x != null)
                                {
                                    slot.Value = null;
                                    slot.Next  = null;
                                    return(x);
                                }
                                else
                                {
                                    Monitor.Wait(slot);
                                }
                            }
                        }
                        catch (ThreadInterruptedException ie)
                        {
                            Object x = slot.Value;
                            if (x != null)
                            {
                                slot.Value = null;
                                slot.Next  = null;
                                Thread.CurrentThread.Interrupt();
                                return(x);
                            }
                            else
                            {
                                slot.Value = Cancelled;
                                throw SystemExtensions.PreserveStackTrace(ie);
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// <see cref="IPuttable.Put"/>
        /// </summary>
        public virtual void  Put(Object x)
        {
            if (x == null)
            {
                throw new ArgumentException();
            }

            // This code is conceptually straightforward, but messy
            // because we need to intertwine handling of put-arrives first
            // vs take-arrives first cases.

            // Outer loop is to handle retry due to cancelled waiting taker
            for (; ;)
            {
                // Get out now if we are interrupted
                Utils.FailFastIfInterrupted();
                // Exactly one of item or slot will be nonnull at end of
                // synchronized block, depending on whether a put or a take
                // arrived first.
                LinkedNode slot;
                LinkedNode item = null;

                lock (this)
                {
                    // Try to match up with a waiting taker; fill and signal it below
                    slot = waitingTakes.Deq();

                    // If no takers yet, create a node and wait below
                    if (slot == null)
                    {
                        waitingPuts.Enq(item = new LinkedNode(x));
                    }
                }

                if (slot != null)
                {
                    // There is a waiting taker.
                    // Fill in the slot created by the taker and signal taker to
                    // continue.
                    lock (slot)
                    {
                        if (slot.Value != Cancelled)
                        {
                            slot.Value = x;
                            Monitor.Pulse(slot);
                            return;
                        }
                        // else the taker has cancelled, so retry outer loop
                    }
                }
                else
                {
                    // Wait for a taker to arrive and take the item.
                    lock (item)
                    {
                        try
                        {
                            while (item.Value != null)
                            {
                                Monitor.Wait(item);
                            }
                            return;
                        }
                        catch (ThreadInterruptedException ie)
                        {
                            // If item was taken, return normally but set interrupt status
                            if (item.Value == null)
                            {
                                Thread.CurrentThread.Interrupt();
                                return;
                            }
                            else
                            {
                                item.Value = Cancelled;
                                throw SystemExtensions.PreserveStackTrace(ie);
                            }
                        }
                    }
                }
            }
        }
        /// <summary> Main barrier code, covering the various policies.</summary>
        private int DoWait(bool timed, TimeSpan duration)
        {
            using (_lock.Lock())
            {
                Generation currentGeneration = _generation;

                if (currentGeneration.isBroken)
                {
                    throw new BrokenBarrierException();
                }

                int index = --_count;
                if (index == 0)
                {
                    bool ranAction = false;
                    try
                    {
                        Action command = _barrierCommand;
                        if (command != null)
                        {
                            command();
                        }
                        ranAction = true;
                        NextGeneration();
                        return(0);
                    }
                    finally
                    {
                        if (!ranAction)
                        {
                            BreakBarrier();
                        }
                    }
                }

                // loop until tripped, broken, interrupted, or timed out
                DateTime deadline = DateTime.UtcNow.Add(duration);
                for (;;)
                {
                    try
                    {
                        if (!timed)
                        {
                            _trip.Await();
                        }
                        else if (duration.Ticks > 0)
                        {
                            _trip.Await(duration);
                            duration = deadline.Subtract(DateTime.UtcNow);
                        }
                    }
                    catch (ThreadInterruptedException e)
                    {
                        if (currentGeneration == _generation && !currentGeneration.isBroken)
                        {
                            BreakBarrier();
                            throw SystemExtensions.PreserveStackTrace(e);
                        }
                        else
                        {
                            // We're about to finish waiting even if we had not
                            // been interrupted, so this interrupt is deemed to
                            // "belong" to subsequent execution.
                            Thread.CurrentThread.Interrupt();
                        }
                    }

                    if (currentGeneration.isBroken)
                    {
                        throw new BrokenBarrierException();
                    }

                    if (currentGeneration != _generation)
                    {
                        return(index);
                    }

                    if (timed && duration.Ticks <= 0)
                    {
                        BreakBarrier();
                        throw new TimeoutException();
                    }
                }
            }
        }