/** * Makes available the permit for the given strand, if it * was not already available. If the strand was blocked on * {@code park} then it will unblock. Otherwise, its next call * to {@code park} is guaranteed not to block. This operation * is not guaranteed to have any effect at all if the given * strand has not been started. * * @param strand the strand to unpark, or {@code null}, in which case this operation has no effect * @param unblocker the synchronization object responsible for the strand unparking */ public static void unpark(Strand strand, Object unblocker) { Strand.unpark(strand, unblocker); }
/** * Makes available the permit for the given strand, if it * was not already available. If the strand was blocked on * {@code park} then it will unblock. Otherwise, its next call * to {@code park} is guaranteed not to block. This operation * is not guaranteed to have any effect at all if the given * strand has not been started. * * @param strand the strand to unpark, or {@code null}, in which case this operation has no effect * @param unblocker the synchronization object responsible for the strand unparking */ public static void unpark(Strand strand, Object unblocker) { if (strand != null) strand.unpark(unblocker); }
/** * Makes available the permit for the given strand, if it * was not already available. If the strand was blocked on * {@code park} then it will unblock. Otherwise, its next call * to {@code park} is guaranteed not to block. This operation * is not guaranteed to have any effect at all if the given * strand has not been started. * * @param strand the strand to unpark, or {@code null}, in which case this operation has no effect */ public static void unpark(Strand strand) { Strand.unpark(strand); }
/** * Makes available the permit for the given strand, if it * was not already available. If the strand was blocked on * {@code park} then it will unblock. Otherwise, its next call * to {@code park} is guaranteed not to block. This operation * is not guaranteed to have any effect at all if the given * strand has not been started. * * @param strand the strand to unpark, or {@code null}, in which case this operation has no effect */ public static void unpark(Thread strand) { Strand.unpark(strand); }
/** * Makes available the permit for the given strand, if it * was not already available. If the strand was blocked on * {@code park} then it will unblock. Otherwise, its next call * to {@code park} is guaranteed not to block. This operation * is not guaranteed to have any effect at all if the given * strand has not been started. * * @param strand the strand to unpark, or {@code null}, in which case this operation has no effect */ public static void unpark(Strand strand) { if (strand != null) strand.unpark(); }
void signal() { waiter.unpark(this); }
public void done() { long count = running.decrementAndGet(); if (count == 0 && waiter != null) { waiter.unpark(); } }
@Override public void signalAll() { for (Strand s : waiters) { record("signalAll", "%s signalling %s", this, s); Strand.unpark(s, owner); } }
/** * Tries to artificially match a data node -- used by remove. */ final boolean tryMatchData() { // assert isData; Object x = item; if (x != null && x != this && casItem(x, null)) { Strand.unpark(waiter, this); return true; } return false; }
@Override public void signal() { final Strand s = waiter; record("signal", "%s signalling %s", this, s); if (s != null) Strand.unpark(s, owner); }
@Override public Object register() { Strand.unpark(Strand.currentStrand()); return null; }
/** * Removes and signals threads from queue for phase. */ private void releaseWaiters(int phase) { QNode q; // first element of queue Strand t; // its strand AtomicReference<QNode> head = (phase & 1) == 0 ? evenQ : oddQ; // int total = 0; // contention profiling // int failed = 0; // contention profiling while ((q = head.get()) != null && q.phase != (int) (root.state >>> PHASE_SHIFT)) { if (head.compareAndSet(q, q.next) && (t = q.strand) != null) { q.strand = null; // System.out.println("PHASER " + (System.currentTimeMillis() % 300000) + " " + (int) (state >>> PHASE_SHIFT) + " " + Fiber.currentFiber() + " " + Thread.currentThread() + " - " + t); Strand.unpark(t); } // else // failed++; // total++; } // if (total > 0) // System.out.println("PHASER: " + Fiber.currentFiber() + " releaseWaiters: " + failed + '/' + total + " " + ((double)failed / total)); }
/** * Wakes up node's successor, if one exists. * * @param node the node */ private void unparkSuccessor(Node node) { /* * If status is negative (i.e., possibly needing signal) try * to clear in anticipation of signalling. It is OK if this * fails or if status is changed by waiting strand. */ int ws = node.waitStatus; if (ws < 0) compareAndSetWaitStatus(node, ws, 0); /* * Strand to unpark is held in successor, which is normally * just the next node. But if cancelled or apparently null, * traverse backwards from tail to find the actual * non-cancelled successor. */ Node s = node.next; if (s == null || s.waitStatus > 0) { s = null; for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } if (s != null) Strand.unpark(s.strand); }
public static void yieldAndUnpark(Strand other, Object blocker) throws SuspendExecution { if (canTransferControl(other)) Fiber.yieldAndUnpark((Fiber) other, blocker); else if (!other.isFiber() && !isCurrentFiber()) { // might be made faster on Linux if SwitchTo syscall is introduced into the kernel. other.unpark(blocker); //Thread.yield(); - it's a shame to yield now as we'll shortly block } else { other.unpark(blocker); //yield(); - it's a shame to yield now as we'll shortly block } }
public static void yieldAndUnpark(Strand other) throws SuspendExecution { if (other.isFiber() && isCurrentFiber()) Fiber.yieldAndUnpark((Fiber) other); else if (!other.isFiber() && !isCurrentFiber()) { // might be made faster on Linux if SwitchTo syscall is introduced into the kernel. other.unpark(); //Thread.yield(); - it's a shame to yield now as we'll shortly block } else { other.unpark(); //yield(); - it's a shame to yield now as we'll shortly block } }
public static void parkAndUnpark(Strand other, Object blocker) throws SuspendExecution { if (canTransferControl(other)) Fiber.parkAndUnpark((Fiber) other, blocker); else if (!other.isFiber() && !isCurrentFiber()) { // might be made faster on Linux if SwitchTo syscall is introduced into the kernel. other.unpark(blocker); LockSupport.park(blocker); } else { other.unpark(blocker); park(blocker); } }
public static void parkAndUnpark(Strand other) throws SuspendExecution { if (canTransferControl(other)) Fiber.parkAndUnpark((Fiber) other); else if (!other.isFiber() && !isCurrentFiber()) { // might be made faster on Linux if SwitchTo syscall is introduced into the kernel. other.unpark(); LockSupport.park(); } else { other.unpark(); park(); } }
private void signalWaitersOnClose() { for (Node p = head; p != null;) { if (!p.isMatched()) { if (!p.isData) { if (p.casItem(null, CHANNEL_CLOSED)) // match waiting requesters with CHANNEL_CLOSED Strand.unpark(p.waiter, this); // ... and wake 'em up } else p.tryMatchData(); } Node n = p.next; if (n != p) p = n; else p = head; } } /////////////////////////////////////////
/** * Transfers a node from a condition queue onto sync queue. * Returns true if successful. * @param node the node * @return true if successfully transferred (else the node was * cancelled before signal) */ final boolean transferForSignal(Node node) { /* * If cannot change waitStatus, the node has been cancelled. */ if (!compareAndSetWaitStatus(node, Node.CONDITION, 0)) return false; /* * Splice onto queue and try to set waitStatus of predecessor to * indicate that strand is (probably) waiting. If cancelled or * attempt to set waitStatus fails, wake up to resync (in which * case the waitStatus can be transiently and harmlessly wrong). */ Node p = enq(node); int ws = p.waitStatus; if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL)) Strand.unpark(node.strand); return true; }
@Override public void signal() { /* * We must wake up the first waiter that is actually parked. Otherwise, by the time the awakened waiter calls * unregister(), another one may block, and we may need to wake that one. */ for (final Strand s : waiters) { if (s.isFiber()) { if (FiberControl.unpark((Fiber) s, owner)) { record("signal", "%s signalled %s", this, s); return; } } else { // TODO: We can't tell (atomically) if a thread is actually parked, so we'll wake them all up. // We may consider a more complex solution, a-la AbstractQueuedSynchronizer for threads // (i.e. with a wrapper node, containing the state) record("signal", "%s signalling %s", this, s); Strand.unpark(s, owner); } } } }