Example #1
0
        bool IChannel.Send(IWaiter w)
        {
            var s = (Waiter <T>)w;

            Debug.Assert(s.Value.IsSome);
            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 = s.Value;
                        Debug.Print("Thread {0}, {1} Send({2}), SetItem suceeded", Thread.CurrentThread.ManagedThreadId, GetType(), wr.Value);
                        wr.Wakeup();
                        return(true);
                    }
                }
                if (!items.Full)
                {
                    Debug.Print("Thread {0}, {1} Send({2}), spare capacity, adding to itemq", Thread.CurrentThread.ManagedThreadId, GetType(), s.Value.Value);
                    items.Enqueue(s.Value.Value);
                    return(true);
                }
                // at capacity, queue our waiter until some capacity is freed up by a recv
                senders.Enqueue(s);
                return(false);
            }
        }
Example #2
0
        bool IChannel.TrySend(IWaiter w)
        {
            var s = (Waiter <T>)w;

            lock (sync) {
                if (closed)
                {
                    return(false);
                }
                if (items.Empty)
                {
                    Waiter <T> wr = receivers.Dequeue();
                    if (wr != null)
                    {
                        wr.Value = s.Value;
                        Debug.Print("Thread {0}, {1} TrySend({2}), waking up receiver", Thread.CurrentThread.ManagedThreadId, GetType(), wr.Value);
                        wr.Wakeup();
                        return(true);
                    }
                }
                if (!items.Full)
                {
                    Debug.Print("Thread {0}, {1} TrySend({2}), add item to queue", Thread.CurrentThread.ManagedThreadId, GetType(), s.Value.Value);
                    items.Enqueue(s.Value.Value);
                    return(true);
                }
            }
            return(false);
        }
Example #3
0
        /// <summary>Try to receive without blocking</summary>
        bool IChannel.TryRecv(IWaiter w)
        {
            var r = (Waiter <T>)w;

            lock (sync) {
                if (!items.Empty)
                {
                    r.Value = Maybe <T> .Some(items.Dequeue());

                    Debug.Print("Thread {0}, {1} TryRecvSelect, removed {2} from itemq", Thread.CurrentThread.ManagedThreadId, GetType(), r.Value);
                    MoveSendQToItemQ();
                    return(true);
                }
                if (!senders.Empty)
                {
                    Waiter <T> s = senders.Dequeue();
                    if (s != null)
                    {
                        Debug.Print("Thread {0}, {1} RecvSelect, waking sender", Thread.CurrentThread.ManagedThreadId, GetType());
                        r.Value = s.Value;
                        s.Wakeup();
                        return(true);
                    }
                }
                if (closed)
                {
                    // closed channels return no value and dont block
                    return(true);
                }
                Debug.Print("Thread {0}, {1} TryRecvSelect, itemq and sendq are empty", Thread.CurrentThread.ManagedThreadId, GetType());
                return(false);
            }
        }
Example #4
0
        public bool TrySend(T v)
        {
            lock (sync) {
                if (closed)
                {
                    return(false);
                }
                if (items.Empty)
                {
                    Waiter <T> wr = receivers.Dequeue();
                    if (wr != null)
                    {
                        wr.Value = Maybe <T> .Some(v);

                        Debug.Print("Thread {0}, {1} TrySend({2}), waking up reveiver", Thread.CurrentThread.ManagedThreadId, GetType(), wr.Value);
                        wr.Wakeup();
                        return(true);
                    }
                }
                if (!items.Full)
                {
                    Debug.Print("Thread {0}, {1} TrySend({2}), add item to queue", Thread.CurrentThread.ManagedThreadId, GetType(), v);
                    items.Enqueue(v);
                    return(true);
                }
            }
            return(false);
        }
Example #5
0
 private void MoveSendQToItemQ()
 {
     if (!senders.Empty)
     {
         Waiter <T> s = senders.Dequeue();
         if (s != null)
         {
             items.Enqueue(s.Value.Value);
             Debug.Print("Thread {0}, {1} MoveSendQToItemQ, waking sender", Thread.CurrentThread.ManagedThreadId, GetType());
             s.Wakeup();
         }
     }
 }
Example #6
0
 /// <remarks>returns <see cref="Maybe{T}.None()"/> if would have to block or if the channel is closed</remarks>
 public Maybe <T> TryRecv()
 {
     lock (sync) {
         if (!items.Empty)
         {
             var v = items.Dequeue();
             MoveSendQToItemQ();
             return(Maybe <T> .Some(v));
         }
         Waiter <T> s = senders.Dequeue();
         if (s != null)
         {
             Debug.Print("Thread {0}, {1} Recv, waking sender, item {2}", Thread.CurrentThread.ManagedThreadId, GetType(), s.Value);
             var mv = s.Value;
             s.Wakeup();
             return(mv);
         }
         return(Maybe <T> .None());
     }
 }
Example #7
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);
        }
Example #8
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);
        }