/// <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);
            }
        }
Beispiel #2
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();
 }
        /// <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);
        }
Beispiel #4
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
                }
            }
        }
        /// <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);
         }
     }
 }
Beispiel #8
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
            }
        }
Beispiel #9
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
                }
            }
        }
 /// <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);
        }