/** * Tests whether this function is called within a fiber. This method <i>might</i> be faster than {@code Fiber.currentFiber() != null}. * * @return {@code true} iff the code that called this method is executing in a fiber. */ public static boolean isCurrentFiber() { return Strand.isCurrentFiber(); }
/** * Retrieves a message from the channels, possibly blocking until one becomes available, but no longer than the specified timeout. * * @param timeout the maximum duration to block waiting for a message. * @param unit the time unit of the timeout. * @return a message, or {@code null} if the channel has been closed and no more messages await (see {@link #isClosed()}), or if * the timeout has expired. * @throws InterruptedException */ public Message receive(long timeout, TimeUnit unit) throws InterruptedException { if (Strand.isCurrentFiber()) throw new IllegalStateException("This method cannot be called on a fiber"); try { return p.receive(timeout, unit); } catch (SuspendExecution e) { throw new AssertionError(e); } }
/** * Retrieves a message from the channels, possibly blocking until one becomes available. * * @return a message, or {@code null} if the channel has been closed and no more messages await (see {@link #isClosed()}). * @throws InterruptedException */ public Message receive() throws InterruptedException { if (Strand.isCurrentFiber()) throw new IllegalStateException("This method cannot be called on a fiber"); try { return p.receive(); } catch (SuspendExecution e) { throw new AssertionError(e); } }
/** * A hint to the scheduler that the current strand is willing to yield * its current use of a processor. The scheduler is free to ignore this * hint. * * <p> * Yield is a heuristic attempt to improve relative progression * between strands that would otherwise over-utilise a CPU. Its use * should be combined with detailed profiling and benchmarking to * ensure that it actually has the desired effect. */ public static void yield() throws SuspendExecution { if (isCurrentFiber()) Fiber.yield(); else Thread.yield(); }
/** * Sends a message to the channel, possibly blocking until there's room available in the channel. * * If the channel is full, this method may block, throw an exception, silently drop the message, or displace an old message from * the channel. The behavior is determined by the channel's {@link Channels.OverflowPolicy OverflowPolicy}, set at construction time. * * @param message */ public void send(Message message) throws InterruptedException { if (Strand.isCurrentFiber()) throw new IllegalStateException("This method cannot be called on a fiber"); try { p.send(message); } catch (SuspendExecution e) { throw new AssertionError(e); } }
/** * Tests whether the current strand has been interrupted. The * <i>interrupted status</i> of the strand is cleared by this method. In * other words, if this method were to be called twice in succession, the * second call would return {@code false} (unless the current strand were * interrupted again, after the first call had cleared its interrupted * status and before the second call had examined it). * * @return {@code true} if the current thread has been interrupted; {@code false} otherwise. * @see #interrupt() * @see #isInterrupted() */ public static boolean interrupted() { if (isCurrentFiber()) return Fiber.interrupted(); else return Thread.interrupted(); }
/** * Causes the currently executing strand to sleep (temporarily cease * execution) for the specified number of milliseconds, subject to * the precision and accuracy of system timers and schedulers. * * @param millis the length of time to sleep in milliseconds * * @throws IllegalArgumentException if the value of {@code millis} is negative * @throws InterruptedException if any strand has interrupted the current strand. The * <i>interrupted status</i> of the current strand is * cleared when this exception is thrown. */ public static void sleep(long millis) throws SuspendExecution, InterruptedException { if (isCurrentFiber()) Fiber.sleep(millis); else Thread.sleep(millis); }
/** * Causes the currently executing strand to sleep (temporarily cease * execution) for the specified duration, subject to * the precision and accuracy of system timers and schedulers. * * @param duration the length of time to sleep in the time unit specified by {@code unit}. * @param unit the time unit of {@code duration}. * * @throws InterruptedException if any strand has interrupted the current strand. The * <i>interrupted status</i> of the current strand is * cleared when this exception is thrown. */ public static void sleep(long duration, TimeUnit unit) throws SuspendExecution, InterruptedException { if (isCurrentFiber()) Fiber.sleep(duration, unit); else unit.sleep(duration); }
/** * Causes the currently executing strand to sleep (temporarily cease * execution) for the specified number of milliseconds plus the specified * number of nanoseconds, subject to the precision and accuracy of system * timers and schedulers. * * @param millis the length of time to sleep in milliseconds * @param nanos {@code 0-999999} additional nanoseconds to sleep * * @throws IllegalArgumentException if the value of {@code millis} is negative, * or the value of {@code nanos} is not in the range {@code 0-999999} * @throws InterruptedException if any strand has interrupted the current strand. The * <i>interrupted status</i> of the current strand is * cleared when this exception is thrown. */ public static void sleep(long millis, int nanos) throws SuspendExecution, InterruptedException { if (isCurrentFiber()) Fiber.sleep(millis, nanos); else Thread.sleep(millis, nanos); }
/** * Sends a message to the channel, possibly blocking until there's room available in the channel, but never longer than the * specified timeout. * * If the channel is full, this method may block, throw an exception, silently drop the message, or displace an old message from * the channel. The behavior is determined by the channel's {@link Channels.OverflowPolicy OverflowPolicy}, set at construction time. * * @param message * @param timeout the maximum duration this method is allowed to wait. * @param unit the timeout's time unit * @return {@code true} if the message has been sent successfully; {@code false} if the timeout has expired. */ public boolean send(Message message, long timeout, TimeUnit unit) throws InterruptedException { if (Strand.isCurrentFiber()) throw new IllegalStateException("This method cannot be called on a fiber"); try { return p.send(message, timeout, unit); } catch (SuspendExecution e) { throw new AssertionError(e); } }
/** * Tries to increment readerOverflow by first setting state * access bits value to RBITS, indicating hold of spinlock, * then updating, then releasing. * * @param s a reader overflow stamp: (s & ABITS) >= RFULL * @return new stamp on success, else zero */ private long tryIncReaderOverflow(long s) { // assert (s & ABITS) >= RFULL if ((s & ABITS) == RFULL) { if (STATE.compareAndSet(this, s, s | RBITS)) { ++readerOverflow; state = s; return s; } } else if ((ThreadLocalRandom.current().nextInt() & OVERFLOW_YIELD_RATE) == 0) if (!Strand.isCurrentFiber()) Thread.yield();//Strand.yield(); return 0L; }
/** * Tries to decrement readerOverflow. * * @param s a reader overflow stamp: (s & ABITS) >= RFULL * @return new stamp on success, else zero */ private long tryDecReaderOverflow(long s) { // assert (s & ABITS) >= RFULL if ((s & ABITS) == RFULL) { if (STATE.compareAndSet(this, s, s | RBITS)) { int r; long next; if ((r = readerOverflow) > 0) { readerOverflow = r - 1; next = s; } else next = s - RUNIT; state = next; return next; } } else if ((ThreadLocalRandom.current().nextInt() & OVERFLOW_YIELD_RATE) == 0) if (!Strand.isCurrentFiber()) Thread.yield();//Strand.yield(); return 0L; }
/** * Prints a stack trace of the current strand to the standard error stream. * This method is used only for debugging. */ @SuppressWarnings({"CallToThreadDumpStack", "CallToPrintStackTrace"}) public static void dumpStack() { if (isCurrentFiber()) Fiber.dumpStack(); else Thread.dumpStack(); }
if (isCurrentFiber()) Fiber.park(nanos, TimeUnit.NANOSECONDS); else
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 } }
if (isCurrentFiber()) Fiber.park(blocker); else
if (isCurrentFiber()) Fiber.park(); else
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 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(); } }
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); } }