< prev index next >

src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java

Print this page

        

@@ -33,10 +33,13 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 package java.util.concurrent.locks;
 
+import java.util.concurrent.TimeUnit;
+
+import jdk.internal.misc.Strands;
 import jdk.internal.misc.Unsafe;
 
 /**
  * Basic thread blocking primitives for creating locks and other
  * synchronization classes.

@@ -139,11 +142,16 @@
 public class LockSupport {
     private LockSupport() {} // Cannot be instantiated.
 
     private static void setBlocker(Thread t, Object arg) {
         // Even though volatile, hotspot doesn't need a write barrier here.
-        U.putReference(t, PARKBLOCKER, arg);
+        U.putReference(t, THREAD_PARKBLOCKER, arg);
+    }
+
+    private static void setBlocker(Fiber<?> f, Object arg) {
+        // Even though volatile, hotspot doesn't need a write barrier here.
+        U.putReference(f, FIBER_PARKBLOCKER, arg);
     }
 
     /**
      * Makes available the permit for the given thread, if it
      * was not already available.  If the thread was blocked on

@@ -154,12 +162,43 @@
      *
      * @param thread the thread to unpark, or {@code null}, in which case
      *        this operation has no effect
      */
     public static void unpark(Thread thread) {
-        if (thread != null)
-            U.unpark(thread);
+        if (thread != null) {
+            Fiber<?> fiber = Strands.getFiber(thread);
+            if (fiber != null) {
+                Strands.unparkFiber(fiber); // can throw RejectedExecutionException
+            } else {
+                U.unpark(thread);
+            }
+        }
+    }
+
+    /**
+     * 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 is a Thread that has not been started.
+     *
+     * @param strand the strand to unpark, or {@code null}, in which case
+     *        this operation has no effect
+     * @throws IllegalArgumentException if strand is not a {@code Thread},
+     *         {@code Fiber} or {@code null}
+     */
+    public static void unpark(Object strand) {
+        if (strand != null) {
+            if (strand instanceof Thread) {
+                unpark((Thread) strand);
+            } else if (strand instanceof Fiber) {
+                Strands.unparkFiber((Fiber<?>) strand);  // can throw RejectedExecutionException
+            } else {
+                throw new IllegalArgumentException();
+            }
+        }
     }
 
     /**
      * Disables the current thread for thread scheduling purposes unless the
      * permit is available.

@@ -187,14 +226,22 @@
      * @param blocker the synchronization object responsible for this
      *        thread parking
      * @since 1.6
      */
     public static void park(Object blocker) {
-        Thread t = Thread.currentThread();
-        setBlocker(t, blocker);
-        U.park(false, 0L);
-        setBlocker(t, null);
+        Object strand = Strands.currentStrand();
+        if (strand instanceof Fiber) {
+            Fiber<?> fiber = (Fiber<?>) strand;
+            setBlocker(fiber, blocker);
+            Strands.parkFiber();
+            setBlocker(fiber, null);
+        } else {
+            Thread thread = (Thread) strand;
+            setBlocker(thread, blocker);
+            U.park(false, 0L);
+            setBlocker(thread, null);
+        }
     }
 
     /**
      * Disables the current thread for thread scheduling purposes, for up to
      * the specified waiting time, unless the permit is available.

@@ -228,14 +275,22 @@
      * @param nanos the maximum number of nanoseconds to wait
      * @since 1.6
      */
     public static void parkNanos(Object blocker, long nanos) {
         if (nanos > 0) {
-            Thread t = Thread.currentThread();
-            setBlocker(t, blocker);
-            U.park(false, nanos);
-            setBlocker(t, null);
+            Object strand = Strands.currentStrand();
+            if (strand instanceof Fiber) {
+                Fiber<?> fiber = (Fiber<?>) strand;
+                setBlocker(fiber, blocker);
+                Strands.parkFiber(nanos);
+                setBlocker(fiber, null);
+            } else {
+                Thread thread = (Thread) strand;
+                setBlocker(thread, blocker);
+                U.park(false, nanos);
+                setBlocker(thread, null);
+            }
         }
     }
 
     /**
      * Disables the current thread for thread scheduling purposes, until

@@ -269,14 +324,24 @@
      * @param deadline the absolute time, in milliseconds from the Epoch,
      *        to wait until
      * @since 1.6
      */
     public static void parkUntil(Object blocker, long deadline) {
-        Thread t = Thread.currentThread();
-        setBlocker(t, blocker);
-        U.park(true, deadline);
-        setBlocker(t, null);
+        Object strand = Strands.currentStrand();
+        if (strand instanceof Fiber) {
+            Fiber<?> fiber = (Fiber<?>) strand;
+            setBlocker(fiber, blocker);
+            long millis = deadline - System.currentTimeMillis();
+            long nanos = TimeUnit.NANOSECONDS.convert(millis, TimeUnit.MILLISECONDS);
+            Strands.parkFiber(nanos);
+            setBlocker(fiber, null);
+        } else {
+            Thread thread = (Thread) strand;
+            setBlocker(thread, blocker);
+            U.park(true, deadline);
+            setBlocker(thread, null);
+        }
     }
 
     /**
      * Returns the blocker object supplied to the most recent
      * invocation of a park method that has not yet unblocked, or null

@@ -290,11 +355,11 @@
      * @since 1.6
      */
     public static Object getBlocker(Thread t) {
         if (t == null)
             throw new NullPointerException();
-        return U.getReferenceVolatile(t, PARKBLOCKER);
+        return U.getReferenceVolatile(t, THREAD_PARKBLOCKER);
     }
 
     /**
      * Disables the current thread for thread scheduling purposes unless the
      * permit is available.

@@ -319,11 +384,16 @@
      * method to return. Callers should re-check the conditions which caused
      * the thread to park in the first place. Callers may also determine,
      * for example, the interrupt status of the thread upon return.
      */
     public static void park() {
-        U.park(false, 0L);
+        Object strand = Strands.currentStrand();
+        if (strand instanceof Fiber) {
+            Strands.parkFiber();
+        } else {
+            U.park(false, 0L);
+        }
     }
 
     /**
      * Disables the current thread for thread scheduling purposes, for up to
      * the specified waiting time, unless the permit is available.

@@ -353,12 +423,18 @@
      * upon return.
      *
      * @param nanos the maximum number of nanoseconds to wait
      */
     public static void parkNanos(long nanos) {
-        if (nanos > 0)
-            U.park(false, nanos);
+        if (nanos > 0) {
+            Object strand = Strands.currentStrand();
+            if (strand instanceof Fiber) {
+                Strands.parkFiber(nanos);
+            } else {
+                U.park(false, nanos);
+            }
+        }
     }
 
     /**
      * Disables the current thread for thread scheduling purposes, until
      * the specified deadline, unless the permit is available.

@@ -388,11 +464,18 @@
      *
      * @param deadline the absolute time, in milliseconds from the Epoch,
      *        to wait until
      */
     public static void parkUntil(long deadline) {
-        U.park(true, deadline);
+        Object strand = Strands.currentStrand();
+        if (strand instanceof Fiber) {
+            long millis = deadline - System.currentTimeMillis();
+            long nanos = TimeUnit.NANOSECONDS.convert(millis, TimeUnit.MILLISECONDS);
+            Strands.parkFiber(nanos);
+        } else {
+            U.park(true, deadline);
+        }
     }
 
     /**
      * Returns the pseudo-randomly initialized or updated secondary seed.
      * Copied from ThreadLocalRandom due to package access restrictions.

@@ -421,12 +504,14 @@
         return U.getLong(thread, TID);
     }
 
     // Hotspot implementation via intrinsics API
     private static final Unsafe U = Unsafe.getUnsafe();
-    private static final long PARKBLOCKER = U.objectFieldOffset
+    private static final long THREAD_PARKBLOCKER = U.objectFieldOffset
             (Thread.class, "parkBlocker");
+    private static final long FIBER_PARKBLOCKER = U.objectFieldOffset
+            (Fiber.class, "parkBlocker");
     private static final long SECONDARY = U.objectFieldOffset
             (Thread.class, "threadLocalRandomSecondarySeed");
     private static final long TID = U.objectFieldOffset
             (Thread.class, "tid");
 
< prev index next >