< prev index next >

src/jdk.incubator.concurrent/share/classes/jdk/incubator/concurrent/StructuredTaskScope.java

Print this page
@@ -208,35 +208,70 @@
   *     }
   *  }
   *
   * <h2><a id="TreeStructure">Tree structure</a></h2>
   *
-  * StructuredTaskScopes form a tree where parent-child relations are established
-  * implicitly when opening a new task scope:
+  * Task scopes form a tree where parent-child relations are established implicitly when
+  * opening a new task scope:
   * <ul>
   *   <li> A parent-child relation is established when a thread started in a task scope
   *   opens its own task scope. A thread started in task scope "A" that opens task scope
   *   "B" establishes a parent-child relation where task scope "A" is the parent of task
   *   scope "B".
   *   <li> A parent-child relation is established with nesting. If a thread opens task
   *   scope "B", then opens task scope "C" (before it closes "B"), then the enclosing task
   *   scope "B" is the parent of the nested task scope "C".
   * </ul>
   *
-  * <p> The tree structure supports confinement checks. The phrase "threads contained in
-  * the task scope" in method descriptions means threads started in the task scope or
-  * descendant scopes. {@code StructuredTaskScope} does not define APIs that exposes the
-  * tree structure at this time.
+  * The <i>descendants</i> of a task scope are the child task scopes that it is a parent
+  * of, plus the descendants of the child task scopes, recursively.
+  *
+  * <p> The tree structure supports:
+  * <ul>
+  *   <li> Inheritance of {@linkplain ScopedValue scoped values} across threads.
+  *   <li> Confinement checks. The phrase "threads contained in the task scope" in method
+  *   descriptions means threads started in the task scope or descendant scopes.
+  * </ul>
+  *
+  * <p> The following example demonstrates the inheritance of a scoped value. A scoped
+  * value {@code USERNAME} is bound to the value "{@code duke}". A {@code StructuredTaskScope}
+  * is created and its {@code fork} method invoked to start a thread to execute {@code
+  * childTask}. The thread inherits the scoped value <em>bindings</em> captured when
+  * creating the task scope. The code in {@code childTask} uses the value of the scoped
+  * value and so reads the value "{@code duke}".
+  * {@snippet lang=java :
+  *     private static final ScopedValue<String> USERNAME = ScopedValue.newInstance();
+  *
+  *     // @link substring="where" target="ScopedValue#where(ScopedValue, Object, Runnable)" :
+  *     ScopedValue.where(USERNAME, "duke", () -> {
+  *         try (var scope = new StructuredTaskScope<String>()) {
+  *
+  *             scope.fork(() -> childTask());           // @highlight substring="fork"
+  *             ...
+  *          }
+  *     });
+  *
+  *     ...
+  *
+  *     String childTask() {
+  *         // @link substring="get" target="ScopedValue#get()" :
+  *         String name = USERNAME.get();   // "duke"
+  *         ...
+  *     }
+  * }
+  *
+  * <p> {@code StructuredTaskScope} does not define APIs that exposes the tree structure
+  * at this time.
   *
   * <p> Unless otherwise specified, passing a {@code null} argument to a constructor
   * or method in this class will cause a {@link NullPointerException} to be thrown.
   *
   * <h2>Memory consistency effects</h2>
   *
   * <p> Actions in the owner thread of, or a thread contained in, the task scope prior to
   * {@linkplain #fork forking} of a {@code Callable} task
-  * <a href="../../../../java.base/java/util/concurrent/package-summary.html#MemoryVisibility">
+  * <a href="{@docRoot}/java.base/java/util/concurrent/package-summary.html#MemoryVisibility">
   * <i>happen-before</i></a> any actions taken by that task, which in turn <i>happen-before</i>
   * the task result is retrieved via its {@code Future}, or <i>happen-before</i> any actions
   * taken in a thread after {@linkplain #join() joining} of the task scope.
   *
   * @jls 17.4.5 Happens-before Order

@@ -278,10 +313,16 @@
       * scope is optionally named for the purposes of monitoring and management. The thread
       * factory is used to {@link ThreadFactory#newThread(Runnable) create} threads when
       * tasks are {@linkplain #fork(Callable) forked}. The task scope is owned by the
       * current thread.
       *
+      * <p> This method captures the current thread's {@linkplain ScopedValue scoped value}
+      * bindings for inheritance by threads created in the task scope. The
+      * <a href="#TreeStructure">Tree Structure</a> section in the class description
+      * details how parent-child relations are established implicitly for the purpose of
+      * inheritance of scoped value bindings.
+      *
       * @param name the name of the task scope, can be null
       * @param factory the thread factory
       */
      public StructuredTaskScope(String name, ThreadFactory factory) {
          this.factory = Objects.requireNonNull(factory, "'factory' is null");

@@ -365,20 +406,23 @@
      protected void handleComplete(Future<T> future) { }
  
      /**
       * Starts a new thread to run the given task.
       *
-      * <p> The new thread is created with the task scope's {@link ThreadFactory}.
+      * <p> The new thread is created with the task scope's {@link ThreadFactory}. It
+      * inherits the current thread's {@linkplain ScopedValue scoped value} bindings. The
+      * bindings must match the bindings captured when the task scope was created.
       *
       * <p> If the task completes before the task scope is {@link #shutdown() shutdown}
-      * then the {@link #handleComplete(Future) handle} method is invoked to consume the
-      * completed task. The {@code handleComplete} method is run when the task completes
-      * with a result or exception. If the {@code Future} {@link Future#cancel(boolean)
-      * cancel} method is used the cancel a task before the task scope is shut down, then
-      * the {@code handleComplete} method is run by the thread that invokes {@code cancel}.
-      * If the task scope shuts down at or around the same time that the task completes or
-      * is cancelled then the {@code handleComplete} method may or may not be invoked.
+      * then the {@link #handleComplete(Future) handleComplete} method is invoked to
+      * consume the completed task. The {@code handleComplete} method is run when the task
+      * completes with a result or exception. If the {@code Future}'s {@link
+      * Future#cancel(boolean) cancel} method is used to cancel a task before the task scope
+      * is shut down, then the {@code handleComplete} method is run by the thread that
+      * invokes {@code cancel}. If the task scope shuts down at or around the same time
+      * that the task completes or is cancelled then the {@code handleComplete} method may
+      * or may not be invoked.
       *
       * <p> If this task scope is {@linkplain #shutdown() shutdown} (or in the process
       * of shutting down) then {@code fork} returns a {@code Future} representing a {@link
       * Future.State#CANCELLED cancelled} task that was not run.
       *

@@ -393,10 +437,12 @@
       * @param <U> the result type
       * @return a future
       * @throws IllegalStateException if this task scope is closed
       * @throws WrongThreadException if the current thread is not the owner or a thread
       * contained in the task scope
+      * @throws StructureViolationException if the current scoped value bindings are not
+      * the same as when the task scope was created
       * @throws RejectedExecutionException if the thread factory rejected creating a
       * thread to run the task
       */
      public <U extends T> Future<U> fork(Callable<? extends U> task) {
          Objects.requireNonNull(task, "'task' is null");

@@ -626,10 +672,16 @@
       * <p> A {@code StructuredTaskScope} is intended to be used in a <em>structured
       * manner</em>. If this method is called to close a task scope before nested task
       * scopes are closed then it closes the underlying construct of each nested task scope
       * (in the reverse order that they were created in), closes this task scope, and then
       * throws {@link StructureViolationException}.
+      *
+      * Similarly, if this method is called to close a task scope while executing with
+      * {@linkplain ScopedValue scoped value} bindings, and the task scope was created
+      * before the scoped values were bound, then {@code StructureViolationException} is
+      * thrown after closing the task scope.
+      *
       * If a thread terminates without first closing task scopes that it owns then
       * termination will cause the underlying construct of each of its open tasks scopes to
       * be closed. Closing is performed in the reverse order that the task scopes were
       * created in. Thread termination may therefore be delayed when the owner has to wait
       * for threads forked in these task scopes to finish.

@@ -822,10 +874,16 @@
           * The task scope is optionally named for the purposes of monitoring and management.
           * The thread factory is used to {@link ThreadFactory#newThread(Runnable) create}
           * threads when tasks are {@linkplain #fork(Callable) forked}. The task scope is
           * owned by the current thread.
           *
+          * <p> This method captures the current thread's {@linkplain ScopedValue scoped value}
+          * bindings for inheritance by threads created in the task scope. The
+          * <a href="StructuredTaskScope.html#TreeStructure">Tree Structure</a> section in
+          * the class description details how parent-child relations are established
+          * implicitly for the purpose of inheritance of scoped value bindings.
+          *
           * @param name the name of the task scope, can be null
           * @param factory the thread factory
           */
          public ShutdownOnSuccess(String name, ThreadFactory factory) {
              super(name, factory);

@@ -998,10 +1056,16 @@
           * The task scope is optionally named for the purposes of monitoring and management.
           * The thread factory is used to {@link ThreadFactory#newThread(Runnable) create}
           * threads when tasks are {@linkplain #fork(Callable) forked}. The task scope
           * is owned by the current thread.
           *
+          * <p> This method captures the current thread's {@linkplain ScopedValue scoped value}
+          * bindings for inheritance by threads created in the task scope. The
+          * <a href="StructuredTaskScope.html#TreeStructure">Tree Structure</a> section in
+          * the class description details how parent-child relations are established
+          * implicitly for the purpose of inheritance of scoped value bindings.
+          *
           * @param name the name of the task scope, can be null
           * @param factory the thread factory
           */
          public ShutdownOnFailure(String name, ThreadFactory factory) {
              super(name, factory);
< prev index next >