private Token receive0() { Node s = new Node(null, false); // the node to append retry: for (; ; ) { // restart on append race Object item = tryMatch(null, null, false); if (item != NO_MATCH) { s.item = item; return new Token(s, null); } Node pred = tryAppend(s, false); if (pred == null) continue retry; // lost race vs opposite mode if (sendClosed) { s.item = CHANNEL_CLOSED; unsplice(pred, s); setReceiveClosed(); return new Token(s, null); } requestUnpark(s, Strand.currentStrand()); return new Token(s, pred); } }
private static ActorRef getCurrentActor() { ActorRef actorRef = LocalActor.self(); if (actorRef == null) { // create a "dummy actor" on the current strand Actor actor = new Actor(Strand.currentStrand(), null, new MailboxConfig(5, OverflowPolicy.THROW)) { @Override protected Object doRun() throws InterruptedException, SuspendExecution { throw new AssertionError(); } }; actorRef = new TempActor(actor); } return actorRef; }
/** * Spins/yields/blocks until node s is matched or caller gives up. * * @param s the waiting node * @param pred the predecessor of s, or s itself if it has no predecessor, or null if unknown (the * null case does not occur in any current calls but may in possible future extensions) * @param e the comparison value for checking match * @param timed if true, wait only until timeout elapses * @param nanos timeout in nanosecs, used only if timed is true * @return matched item, or e if unmatched on interrupt or timeout */ private Message awaitMatch(Node s, Node pred, Message e, boolean timed, long nanos) throws SuspendExecution { long lastTime = timed ? System.nanoTime() : 0L; Strand w = Strand.currentStrand(); int spins = (w.isFiber() ? 0 : -1); // no spins in fiber; otherwise, initialized after first item and cancel checks ThreadLocalRandom randomYields = null; // bound if needed if (spins == 0) requestUnpark(s, w); for (; ; ) { Object item = s.item; if (item == CHANNEL_CLOSED) setReceiveClosed(); if (item != e) { // matched // assert item != s; s.forgetContents(); // avoid garbage return this.<Message>cast(item); } if ((w.isInterrupted() || (timed && nanos <= 0)) && s.casItem(e, s)) { // cancel unsplice(pred, s); return e; } if (spins < 0) { // establish spins at/near front if ((spins = spinsFor(pred, s.isData)) > 0) randomYields = ThreadLocalRandom.current(); } else if (spins > 0) { // spin --spins; if (randomYields.nextInt(CHAINED_SPINS) == 0) Strand.yield(); // occasionally yield } else if (s.waiter == null) { requestUnpark(s, w); // request unpark then recheck } else if (timed) { long now = System.nanoTime(); if ((nanos -= now - lastTime) > 0) Strand.parkNanos(this, nanos); lastTime = now; } else { Strand.park(this); } } }