public bool Enqueue(T value, TimeSpan timeout)
        {
            _monitor.Lock();
            try
            {
                if (_receiveRequests.Count > 0)
                {
                    var receiver = _receiveRequests.First !;
                    _receiveRequests.RemoveFirst();
                    receiver.Value.Element = value;
                    receiver.Value.IsDone  = true;
                    receiver.Value.Condition.Signal();
                    return(true);
                }

                if (timeout == TimeSpan.Zero)
                {
                    return(false);
                }

                var node     = _sendRequests.AddLast(new SendRequest(_monitor.NewCondition(), value));
                var deadline = Deadline.FromTimeout(timeout);
                while (true)
                {
                    TimeSpan remaining = deadline.Remaining();
                    try
                    {
                        node.Value.Condition.Await(remaining);
                    }
                    catch (ThreadInterruptedException)
                    {
                        if (node.Value.IsDone)
                        {
                            Thread.CurrentThread.Interrupt();
                            return(true);
                        }

                        _sendRequests.Remove(node);
                        throw;
                    }

                    if (node.Value.IsDone)
                    {
                        return(true);
                    }

                    remaining = deadline.Remaining();
                    if (remaining <= TimeSpan.Zero)
                    {
                        _sendRequests.Remove(node);
                        return(false);
                    }
                }
            }
            finally
            {
                _monitor.Unlock();
            }
        }
Example #2
0
 public void Await(TimeSpan timeout)
 {
     Monitor.Enter(_conditionMonitor);
     _parentLock.Unlock();
     try
     {
         Monitor.Wait(_conditionMonitor, timeout);
     }
     finally
     {
         Monitor.Exit(_conditionMonitor);
         _parentLock.LockNonInterruptibly(out var wasInterrupted);
         if (wasInterrupted)
         {
             throw new ThreadInterruptedException();
         }
     }
 }