29 import java.security.AccessController;
30 import java.security.PrivilegedAction;
31 import java.time.Duration;
32 import java.time.Instant;
33 import java.util.Comparator;
34 import java.util.Objects;
35 import java.util.Optional;
36 import java.util.Set;
37 import java.util.concurrent.Callable;
38 import java.util.concurrent.CancellationException;
39 import java.util.concurrent.ConcurrentHashMap;
40 import java.util.concurrent.ExecutionException;
41 import java.util.concurrent.Future;
42 import java.util.concurrent.FutureTask;
43 import java.util.concurrent.RejectedExecutionException;
44 import java.util.concurrent.ThreadFactory;
45 import java.util.concurrent.TimeoutException;
46 import java.util.concurrent.TimeUnit;
47 import java.util.concurrent.locks.ReentrantLock;
48 import java.util.function.Function;
49 import jdk.internal.misc.PreviewFeatures;
50 import jdk.internal.misc.ThreadFlock;
51
52 /**
53 * A basic API for <em>structured concurrency</em>. {@code StructuredTaskScope} supports
54 * cases where a task splits into several concurrent subtasks, to be executed in their
55 * own threads, and where the subtasks must complete before the main task continues. A
56 * {@code StructuredTaskScope} can be used to ensure that the lifetime of a concurrent
57 * operation is confined by a <em>syntax block</em>, just like that of a sequential
58 * operation in structured programming.
59 *
60 * <h2>Basic usage</h2>
61 *
62 * A {@code StructuredTaskScope} is created with one of its public constructors. It defines
63 * the {@link #fork(Callable) fork} method to start a thread to execute a task, the {@link
64 * #join() join} method to wait for all threads to finish, and the {@link #close() close}
65 * method to close the task scope. The API is intended to be used with the {@code
66 * try-with-resources} construct. The intention is that code in the <em>block</em> uses
67 * the {@code fork} method to fork threads to execute the subtasks, wait for the threads
68 * to finish with the {@code join} method, and then <em>process the results</em>.
69 * Processing of results may include handling or re-throwing of exceptions.
318 * <p> This method captures the current thread's {@linkplain ScopedValue scoped value}
319 * bindings for inheritance by threads created in the task scope. The
320 * <a href="#TreeStructure">Tree Structure</a> section in the class description
321 * details how parent-child relations are established implicitly for the purpose of
322 * inheritance of scoped value bindings.
323 *
324 * @param name the name of the task scope, can be null
325 * @param factory the thread factory
326 */
327 public StructuredTaskScope(String name, ThreadFactory factory) {
328 this.factory = Objects.requireNonNull(factory, "'factory' is null");
329 this.flock = ThreadFlock.open(name);
330 }
331
332 /**
333 * Creates an unnamed structured task scope that creates virtual threads. The task
334 * scope is owned by the current thread.
335 *
336 * <p> This constructor is equivalent to invoking the 2-arg constructor with a name
337 * of {@code null} and a thread factory that creates virtual threads.
338 *
339 * @throws UnsupportedOperationException if preview features are not enabled
340 */
341 public StructuredTaskScope() {
342 PreviewFeatures.ensureEnabled();
343 this.factory = Thread.ofVirtual().factory();
344 this.flock = ThreadFlock.open(null);
345 }
346
347 /**
348 * Throws WrongThreadException if the current thread is not the owner.
349 */
350 private void ensureOwner() {
351 if (Thread.currentThread() != flock.owner())
352 throw new WrongThreadException("Current thread not owner");
353 }
354
355 /**
356 * Throws WrongThreadException if the current thread is not the owner
357 * or a thread contained in the tree.
358 */
359 private void ensureOwnerOrContainsThread() {
360 Thread currentThread = Thread.currentThread();
361 if (currentThread != flock.owner() && !flock.containsThread(currentThread))
362 throw new WrongThreadException("Current thread not owner or thread in the tree");
|
29 import java.security.AccessController;
30 import java.security.PrivilegedAction;
31 import java.time.Duration;
32 import java.time.Instant;
33 import java.util.Comparator;
34 import java.util.Objects;
35 import java.util.Optional;
36 import java.util.Set;
37 import java.util.concurrent.Callable;
38 import java.util.concurrent.CancellationException;
39 import java.util.concurrent.ConcurrentHashMap;
40 import java.util.concurrent.ExecutionException;
41 import java.util.concurrent.Future;
42 import java.util.concurrent.FutureTask;
43 import java.util.concurrent.RejectedExecutionException;
44 import java.util.concurrent.ThreadFactory;
45 import java.util.concurrent.TimeoutException;
46 import java.util.concurrent.TimeUnit;
47 import java.util.concurrent.locks.ReentrantLock;
48 import java.util.function.Function;
49 import jdk.internal.misc.ThreadFlock;
50
51 /**
52 * A basic API for <em>structured concurrency</em>. {@code StructuredTaskScope} supports
53 * cases where a task splits into several concurrent subtasks, to be executed in their
54 * own threads, and where the subtasks must complete before the main task continues. A
55 * {@code StructuredTaskScope} can be used to ensure that the lifetime of a concurrent
56 * operation is confined by a <em>syntax block</em>, just like that of a sequential
57 * operation in structured programming.
58 *
59 * <h2>Basic usage</h2>
60 *
61 * A {@code StructuredTaskScope} is created with one of its public constructors. It defines
62 * the {@link #fork(Callable) fork} method to start a thread to execute a task, the {@link
63 * #join() join} method to wait for all threads to finish, and the {@link #close() close}
64 * method to close the task scope. The API is intended to be used with the {@code
65 * try-with-resources} construct. The intention is that code in the <em>block</em> uses
66 * the {@code fork} method to fork threads to execute the subtasks, wait for the threads
67 * to finish with the {@code join} method, and then <em>process the results</em>.
68 * Processing of results may include handling or re-throwing of exceptions.
317 * <p> This method captures the current thread's {@linkplain ScopedValue scoped value}
318 * bindings for inheritance by threads created in the task scope. The
319 * <a href="#TreeStructure">Tree Structure</a> section in the class description
320 * details how parent-child relations are established implicitly for the purpose of
321 * inheritance of scoped value bindings.
322 *
323 * @param name the name of the task scope, can be null
324 * @param factory the thread factory
325 */
326 public StructuredTaskScope(String name, ThreadFactory factory) {
327 this.factory = Objects.requireNonNull(factory, "'factory' is null");
328 this.flock = ThreadFlock.open(name);
329 }
330
331 /**
332 * Creates an unnamed structured task scope that creates virtual threads. The task
333 * scope is owned by the current thread.
334 *
335 * <p> This constructor is equivalent to invoking the 2-arg constructor with a name
336 * of {@code null} and a thread factory that creates virtual threads.
337 */
338 public StructuredTaskScope() {
339 this.factory = Thread.ofVirtual().factory();
340 this.flock = ThreadFlock.open(null);
341 }
342
343 /**
344 * Throws WrongThreadException if the current thread is not the owner.
345 */
346 private void ensureOwner() {
347 if (Thread.currentThread() != flock.owner())
348 throw new WrongThreadException("Current thread not owner");
349 }
350
351 /**
352 * Throws WrongThreadException if the current thread is not the owner
353 * or a thread contained in the tree.
354 */
355 private void ensureOwnerOrContainsThread() {
356 Thread currentThread = Thread.currentThread();
357 if (currentThread != flock.owner() && !flock.containsThread(currentThread))
358 throw new WrongThreadException("Current thread not owner or thread in the tree");
|