Exemple #1
0
        //
        // Replies to the rendezvous identified by the specified token.
        //

        public void Reply(StRendezvousToken token, R response)
        {
            SendWaitNode <T, R> swn = token.sender as SendWaitNode <T, R>;

            if (swn == null)
            {
                throw new ArgumentException("token");
            }
            swn.response = response;
            swn.Unpark(StParkStatus.Success);
        }
Exemple #2
0
        //
        // Receives a message through the rendezvous channel.
        //

        public bool Receive(out T request, out StRendezvousToken token, StCancelArgs cargs)
        {
            return(channel.Receive(out request, out token, cargs));
        }
Exemple #3
0
            //
            // Receives a message, activating the specified cancellers.
            //

            internal override bool Receive(out T request, out StRendezvousToken token,
                                           StCancelArgs cargs)
            {
                RecvWaitNode <T, R> wn = null;

                do
                {
                    WaitNode t = top;
                    if (t == null || t.type == ReqType.Receive)
                    {
                        //
                        // The stack is empty or the wait note at the top of the
                        // stack belongs to a receiver thread. In this case, we must
                        // create a wait node and push it onto the stack.
                        //

                        if (wn == null)
                        {
                            if (cargs.Timeout == 0)
                            {
                                request = default(T);
                                token   = new StRendezvousToken(null);
                                return(false);
                            }
                            wn = new RecvWaitNode <T, R>();
                        }
                        wn.next = t;
                        if (Interlocked.CompareExchange <WaitNode>(ref top, wn, t) == t)
                        {
                            break;
                        }
                    }
                    else
                    {
                        //
                        // The top wait node belongs to a sender thread; so, try to
                        // pop it from the stack.
                        //

                        if (Interlocked.CompareExchange <WaitNode>(ref top, t.next, t) == t)
                        {
                            //
                            // Try to lock the associated parker and, if succeed, initiate
                            // the rendezvous with its owner thread.
                            //

                            if (t.TryLock())
                            {
                                SendWaitNode <T, R> swn = (SendWaitNode <T, R>)t;
                                request = swn.request;
                                if (swn.type == ReqType.SendOnly)
                                {
                                    token = new StRendezvousToken(null);
                                    swn.Unpark(StParkStatus.Success);
                                }
                                else
                                {
                                    token = new StRendezvousToken(swn);
                                }
                                return(true);
                            }
                        }
                    }
                } while (true);

                //
                // Park the current thread, activating the specified cancellers.
                //

                int ws = wn.Park(cargs);

                //
                // If succeed, retrive the request from the wait node, build a
                // rendezvous token and return success.
                //

                if (ws == StParkStatus.Success)
                {
                    request = wn.request;
                    token   = new StRendezvousToken(wn.sender);
                    return(true);
                }

                //
                // The receive was cancelled; so, unlink the wait node from
                // the wait queue and return the failure approriately.
                //

                Unlink(wn);
                request = default(T);
                token   = new StRendezvousToken(null);
                StCancelArgs.ThrowIfException(ws);
                return(false);
            }
Exemple #4
0
            //
            // Receives a message, activativating the specified cancellers.
            //

            internal override bool Receive(out T request, out StRendezvousToken token,
                                           StCancelArgs cargs)
            {
                RecvWaitNode <T, R> wn = null;
                WaitNode            pred;

                do
                {
                    WaitNode h = head;
                    WaitNode t = tail;
                    WaitNode hn;
                    if ((hn = h.next) == null || hn.type == ReqType.Receive)
                    {
                        //
                        // The wait queue is empty or contains only receiver
                        // wait nodes. So, do the consistency checks in order to
                        // insert our wait node.
                        //

                        WaitNode tn;
                        if ((tn = t.next) != null)
                        {
                            AdvanceTail(t, tn);
                            continue;
                        }

                        //
                        // Create a wait node, if we don't have one. However,
                        // return failure if a null timeout was specified.
                        //

                        if (wn == null)
                        {
                            if (cargs.Timeout == 0)
                            {
                                request = default(T);
                                token   = new StRendezvousToken(null);
                                return(false);
                            }
                            wn = new RecvWaitNode <T, R>();
                        }

                        //
                        // Try to enqueue the wait node.
                        //

                        if (t.CasNext(null, wn))
                        {
                            AdvanceTail(t, wn);
                            pred = t;
                            break;
                        }
                    }
                    else
                    {
                        //
                        // There is a sender wait node at the front of the queue.
                        // So, try to remove it to initiate the rendezvous.
                        //

                        if (AdvanceHead(h, hn))
                        {
                            if (hn.TryLock())
                            {
                                SendWaitNode <T, R> swn = (SendWaitNode <T, R>)hn;

                                //
                                // Get the request, then, If this is a send only
                                // request build a null rendezvous token and unpark
                                // the sender thread; otherwise, build a rendezvous token
                                // with the sender wait node.
                                //

                                request = swn.request;
                                if (swn.type == ReqType.SendOnly)
                                {
                                    token = new StRendezvousToken(null);
                                    swn.Unpark(StParkStatus.Success);
                                }
                                else
                                {
                                    token = new StRendezvousToken(swn);
                                }
                                return(true);
                            }
                        }
                    }
                } while (true);

                //
                // Park the current thread, activating the specified cancellers.
                //

                int ws = wn.Park(cargs);

                //
                // If succeed, retrive the request and the rendezvous token
                // from the wait node and return success.
                //

                if (ws == StParkStatus.Success)
                {
                    request = wn.request;
                    token   = new StRendezvousToken(wn.sender);
                    return(true);
                }

                //
                // The receive was cancelled; so, unlink our wait node from
                // the wait queue and report the failure appropriately.
                //

                Unlink(wn, pred);
                request = default(T);
                token   = default(StRendezvousToken);
                StCancelArgs.ThrowIfException(ws);
                return(false);
            }
Exemple #5
0
            //
            // Receives a message through the channel.
            //

            internal abstract bool Receive(out T request, out StRendezvousToken token,
                                           StCancelArgs cargs);