Beispiel #1
0
        /// <summary>Returns an item, blocking if not ready</summary>
        /// <remarks>returns <see cref="Maybe{T}.None()"/> without blocking if the channel is closed</remarks>
        public Maybe <T> Recv()
        {
            Waiter <T> r;

            lock (sync) {
                if (!items.Empty)
                {
                    var value = items.Dequeue();
                    Debug.Print("Thread {0}, {1} Recv, removed item from itemq", Thread.CurrentThread.ManagedThreadId, GetType());
                    MoveSendQToItemQ();
                    return(Maybe <T> .Some(value));
                }
                Waiter <T> s = senders.Dequeue();
                if (s != null)
                {
                    Debug.Print("Thread {0}, {1} Recv, waking sender", Thread.CurrentThread.ManagedThreadId, GetType());
                    var mv = s.Value;
                    s.Wakeup();
                    return(mv);
                }
                if (closed)
                {
                    Debug.Print("Thread {0}, {1} Recv, Channel is closed", Thread.CurrentThread.ManagedThreadId, GetType());
                    return(Maybe <T> .None());
                }
                r = WaiterPool <T> .Get();

                receivers.Enqueue(r);
            }
            // wait for a sender to signal it has sent
            Debug.Print("Thread {0}, {1} Recv, waiting", Thread.CurrentThread.ManagedThreadId, GetType());
            r.WaitOne();
            Debug.Print("Thread {0}, {1} Recv, woke up", Thread.CurrentThread.ManagedThreadId, GetType());
            var v = r.Value;

            WaiterPool <T> .Put(r);

            return(v);
        }
Beispiel #2
0
        /// <summary>Send a value, adds it to the item queue or blocks until the queue is no longer full</summary>
        public void Send(T v)
        {
            Waiter <T> s;

            lock (sync) {
                if (closed)
                {
                    throw new ClosedChannelException("You cannot send on a closed Channel");
                }
                if (items.Empty)
                {
                    Waiter <T> wr = receivers.Dequeue();
                    if (wr != null)
                    {
                        wr.Value = Maybe <T> .Some(v);

                        Debug.Print("Thread {0}, {1} Send({2}), SetItem succeeded", Thread.CurrentThread.ManagedThreadId, GetType(), wr.Value);
                        wr.Wakeup();
                        return;
                    }
                }
                if (!items.Full)
                {
                    Debug.Print("Thread {0}, {1} Send({2}), spare capacity, adding to itemq", Thread.CurrentThread.ManagedThreadId, GetType(), v);
                    items.Enqueue(v);
                    return;
                }
                // at capacity, queue our waiter until some capacity is freed up by a recv
                s = WaiterPool <T> .Get(v);

                senders.Enqueue(s);
            }
            // wait for the receiver to wake us up
            Debug.Print("Thread {0}, {1} Send({2}), waiting ", Thread.CurrentThread.ManagedThreadId, GetType(), v);
            s.WaitOne();
            Debug.Print("Thread {0}, {1} Send({2}), woke up after waiting ", Thread.CurrentThread.ManagedThreadId, GetType(), v);
            WaiterPool <T> .Put(s);
        }
Beispiel #3
0
 void IChannel.ReleaseWaiter(IWaiter h)
 {
     WaiterPool <T> .Put((Waiter <T>) h);
 }
Beispiel #4
0
 /// <summary>Gets a waiter for use in RecvSelect</summary>
 IWaiter IChannel.GetWaiter()
 {
     return(WaiterPool <T> .Get());
 }