// // 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); }
// // 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)); }
// // 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); }
// // 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); }
// // Receives a message through the channel. // internal abstract bool Receive(out T request, out StRendezvousToken token, StCancelArgs cargs);