Пример #1
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);
            }
Пример #2
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);
            }
Пример #3
0
            //
            // Sends a message, activating the specified cancellers.
            //

            internal override bool Send(ReqType type, T request, out R response,
                                        StCancelArgs cargs)
            {
                SendWaitNode <T, R> wn   = null;
                WaitNode            pred = null;
                bool enableCancel        = true;

                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 sender
                        // 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,
                        // if a null timeout was specified, return failure.
                        //

                        if (wn == null)
                        {
                            if (cargs.Timeout == 0)
                            {
                                response = default(R);
                                return(false);
                            }
                            wn = new SendWaitNode <T, R>(type, request);
                        }

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

                        if (t.CasNext(null, wn))
                        {
                            //
                            // Set the new tail, save the predecessor wait node
                            // and break the loop.
                            //

                            AdvanceTail(t, wn);
                            pred = t;
                            break;
                        }
                    }
                    else
                    {
                        //
                        // It seems that the wait node that is at front of the queue
                        // belongs to a receive thread; so, try to remove it and
                        // to initiate the rendezvous with the underlying thread.
                        //

                        if (AdvanceHead(h, hn))
                        {
                            if (hn.TryLock())
                            {
                                //
                                // We locked the receiver's wait node. So, get
                                // the request message.
                                //

                                RecvWaitNode <T, R> rwn = (RecvWaitNode <T, R>)hn;
                                rwn.request = request;

                                //
                                // If this a send only request, sets the sender to null,
                                // unpark the receiver thread and return success.
                                //

                                if (type == ReqType.SendOnly)
                                {
                                    rwn.sender = null;
                                    rwn.Unpark(StParkStatus.Success);
                                    response = default(R);
                                    return(true);
                                }

                                //
                                // This is a send and reply request. So, create a wait
                                // node in order to park the current thread and pass the
                                // wait node to the receiver through the rendezvous token.
                                //

                                if (wn == null)
                                {
                                    wn = new SendWaitNode <T, R>(ReqType.SendWaitReply);
                                }
                                rwn.sender = wn;
                                wn.SelfCancel();

                                //
                                // Unpark the receiver thread and go to wait until
                                // reply. After the rendezvous is initiated the
                                // cancellers are deactivated.
                                //

                                rwn.Unpark(StParkStatus.Success);
                                enableCancel = false;
                                break;
                            }
                        }
                    }
                } while (true);

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

                int ws;

                if (enableCancel)
                {
                    ws = wn.Park(cargs);
                }
                else
                {
                    wn.Park();
                    ws = StParkStatus.Success;
                }

                //
                // If succeed, retrieve the response from the wait node
                // and return success.
                //

                if (ws == StParkStatus.Success)
                {
                    response = wn.response;
                    return(true);
                }

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

                Unlink(wn, pred);
                response = default(R);
                StCancelArgs.ThrowIfException(ws);
                return(false);
            }
Пример #4
0
            //
            // Sends a message, activating the specified cancellers.
            //

            internal override bool Send(ReqType type, T request, out R response,
                                        StCancelArgs cargs)
            {
                SendWaitNode <T, R> wn = null;
                bool enableCancel      = true;

                do
                {
                    WaitNode t;
                    if ((t = top) == null || t.type != ReqType.Receive)
                    {
                        //
                        // The stack is empty or the first wait node belongs
                        // to a sender thread.
                        //

                        if (wn == null)
                        {
                            if (cargs.Timeout == 0)
                            {
                                response = default(R);
                                return(false);
                            }
                            wn = new SendWaitNode <T, R>(type, request);
                        }
                        wn.next = t;
                        if (Interlocked.CompareExchange <WaitNode>(ref top, wn, t) == t)
                        {
                            break;
                        }
                    }
                    else
                    {
                        //
                        // The top wait node belongs to a receiver 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())
                            {
                                RecvWaitNode <T, R> rwn = (RecvWaitNode <T, R>)t;
                                rwn.request = request;
                                if (type == ReqType.SendOnly)
                                {
                                    rwn.sender = null;
                                    rwn.Unpark(StParkStatus.Success);
                                    response = default(R);
                                    return(true);
                                }
                                if (wn == null)
                                {
                                    wn = new SendWaitNode <T, R>(ReqType.SendWaitReply);
                                }

                                rwn.sender = wn;
                                wn.SelfCancel();
                                rwn.Unpark(StParkStatus.Success);
                                enableCancel = false;
                                break;
                            }
                        }
                    }
                } while (true);

                //
                // Park the current thread, activating the specified cancellers,
                // but only if the rendezvous wasn't initiated.
                //

                int ws;

                if (enableCancel)
                {
                    ws = wn.Park(cargs);
                }
                else
                {
                    wn.Park();
                    ws = StParkStatus.Success;
                }

                //
                // If succeed, retrive the response and return success.
                //

                if (ws == StParkStatus.Success)
                {
                    response = wn.response;
                    return(true);
                }

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

                Unlink(wn);
                response = default(R);
                StCancelArgs.ThrowIfException(ws);
                return(false);
            }