ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ForkJoinWorkerThread.java
Revision: 1.83
Committed: Fri Mar 18 16:01:42 2022 UTC (2 years, 2 months ago) by dl
Branch: MAIN
Changes since 1.82: +49 -16 lines
Log Message:
jdk17+ suppressWarnings, FJ updates

File Contents

# User Rev Content
1 jsr166 1.1 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3     * Expert Group and released to the public domain, as explained at
4 jsr166 1.46 * http://creativecommons.org/publicdomain/zero/1.0/
5 jsr166 1.1 */
6    
7     package java.util.concurrent;
8    
9 jsr166 1.74 import java.security.AccessController;
10 dl 1.83 import java.security.AccessControlContext;
11 jsr166 1.74 import java.security.PrivilegedAction;
12 dl 1.83 import java.security.ProtectionDomain;
13 dl 1.60
14 jsr166 1.1 /**
15 jsr166 1.40 * A thread managed by a {@link ForkJoinPool}, which executes
16     * {@link ForkJoinTask}s.
17     * This class is subclassable solely for the sake of adding
18     * functionality -- there are no overridable methods dealing with
19     * scheduling or execution. However, you can override initialization
20     * and termination methods surrounding the main task processing loop.
21     * If you do create such a subclass, you will also need to supply a
22 jsr166 1.57 * custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to
23 jsr166 1.76 * {@linkplain ForkJoinPool#ForkJoinPool(int, ForkJoinWorkerThreadFactory,
24     * UncaughtExceptionHandler, boolean, int, int, int, Predicate, long, TimeUnit)
25     * use it} in a {@code ForkJoinPool}.
26 jsr166 1.1 *
27     * @since 1.7
28     * @author Doug Lea
29     */
30     public class ForkJoinWorkerThread extends Thread {
31     /*
32 dl 1.14 * ForkJoinWorkerThreads are managed by ForkJoinPools and perform
33 dl 1.52 * ForkJoinTasks. For explanation, see the internal documentation
34     * of class ForkJoinPool.
35 dl 1.55 *
36 dl 1.79 * This class just maintains links to its pool and WorkQueue.
37 jsr166 1.1 */
38    
39 dl 1.52 final ForkJoinPool pool; // the pool this thread works in
40 dl 1.56 final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics
41 dl 1.54
42     /**
43 dl 1.79 * Full nonpublic constructor.
44 jsr166 1.1 */
45 dl 1.79 ForkJoinWorkerThread(ThreadGroup group, ForkJoinPool pool,
46 dl 1.83 boolean useSystemClassLoader) {
47 dl 1.79 super(group, null, pool.nextWorkerThreadName(), 0L);
48     UncaughtExceptionHandler handler = (this.pool = pool).ueh;
49 dl 1.83 this.workQueue = new ForkJoinPool.WorkQueue(this, 0);
50 dl 1.79 super.setDaemon(true);
51     if (handler != null)
52     super.setUncaughtExceptionHandler(handler);
53     if (useSystemClassLoader)
54     super.setContextClassLoader(ClassLoader.getSystemClassLoader());
55 dl 1.14 }
56    
57 jsr166 1.1 /**
58 dl 1.79 * Creates a ForkJoinWorkerThread operating in the given thread group and
59     * pool.
60     *
61     * @param group if non-null, the thread group for this thread
62     * @param pool the pool this thread works in
63     * @throws NullPointerException if pool is null
64 jsr166 1.74 */
65 dl 1.83 ForkJoinWorkerThread(ThreadGroup group, ForkJoinPool pool) {
66     this(group, pool, false);
67 jsr166 1.74 }
68    
69     /**
70 dl 1.79 * Creates a ForkJoinWorkerThread operating in the given pool.
71     *
72     * @param pool the pool this thread works in
73     * @throws NullPointerException if pool is null
74 dl 1.60 */
75 dl 1.79 protected ForkJoinWorkerThread(ForkJoinPool pool) {
76 dl 1.83 this(null, pool, false);
77 dl 1.60 }
78    
79     /**
80 jsr166 1.1 * Returns the pool hosting this thread.
81     *
82     * @return the pool
83     */
84     public ForkJoinPool getPool() {
85     return pool;
86     }
87    
88     /**
89 jsr166 1.59 * Returns the unique index number of this thread in its pool.
90     * The returned value ranges from zero to the maximum number of
91     * threads (minus one) that may exist in the pool, and does not
92     * change during the lifetime of the thread. This method may be
93     * useful for applications that track status or collect results
94     * per-worker-thread rather than per-task.
95 jsr166 1.1 *
96     * @return the index number
97     */
98     public int getPoolIndex() {
99 dl 1.65 return workQueue.getPoolIndex();
100 dl 1.45 }
101    
102 jsr166 1.1 /**
103 dl 1.14 * Initializes internal state after construction but before
104     * processing any tasks. If you override this method, you must
105 jsr166 1.39 * invoke {@code super.onStart()} at the beginning of the method.
106 dl 1.14 * Initialization requires care: Most fields must have legal
107     * default values, to ensure that attempted accesses from other
108     * threads work correctly even before this thread starts
109     * processing tasks.
110 jsr166 1.1 */
111 dl 1.14 protected void onStart() {
112     }
113 jsr166 1.1
114     /**
115 dl 1.14 * Performs cleanup associated with termination of this worker
116     * thread. If you override this method, you must invoke
117     * {@code super.onTermination} at the end of the overridden method.
118 jsr166 1.4 *
119 dl 1.14 * @param exception the exception causing this thread to abort due
120     * to an unrecoverable error, or {@code null} if completed normally
121 jsr166 1.1 */
122 dl 1.14 protected void onTermination(Throwable exception) {
123 jsr166 1.1 }
124    
125     /**
126     * This method is required to be public, but should never be
127     * called explicitly. It performs the main run loop to execute
128 jsr166 1.40 * {@link ForkJoinTask}s.
129 jsr166 1.1 */
130     public void run() {
131 dl 1.79 Throwable exception = null;
132     ForkJoinPool p = pool;
133     ForkJoinPool.WorkQueue w = workQueue;
134     if (p != null && w != null) { // skip on failed initialization
135 dl 1.52 try {
136 dl 1.79 p.registerWorker(w);
137 dl 1.60 onStart();
138 dl 1.79 p.runWorker(w);
139 dl 1.52 } catch (Throwable ex) {
140 dl 1.60 exception = ex;
141 dl 1.52 } finally {
142 dl 1.60 try {
143     onTermination(exception);
144     } catch (Throwable ex) {
145     if (exception == null)
146     exception = ex;
147     } finally {
148 dl 1.79 p.deregisterWorker(this, exception);
149 dl 1.60 }
150     }
151     }
152     }
153    
154     /**
155     * A worker thread that has no permissions, is not a member of any
156 jsr166 1.74 * user-defined ThreadGroup, uses the system class loader as
157     * thread context class loader, and erases all ThreadLocals after
158 dl 1.60 * running each top-level task.
159     */
160     static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread {
161     /** The ThreadGroup for all InnocuousForkJoinWorkerThreads */
162 dl 1.83 private static final ThreadGroup innocuousThreadGroup;
163     @SuppressWarnings("removal")
164     private static final AccessControlContext innocuousACC;
165     InnocuousForkJoinWorkerThread(ForkJoinPool pool) {
166     super(innocuousThreadGroup, pool, true);
167     }
168 dl 1.60
169 dl 1.83 @Override @SuppressWarnings("removal")
170     protected void onStart() {
171     ForkJoinPool.WorkQueue w = workQueue;
172     if (w != null)
173     w.setInnocuous();
174     Thread t = Thread.currentThread();
175     ThreadLocalRandom.setInheritedAccessControlContext(t, innocuousACC);
176     ThreadLocalRandom.eraseThreadLocals(t);
177 dl 1.60 }
178    
179     @Override // to silently fail
180     public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) { }
181    
182     @Override // paranoically
183     public void setContextClassLoader(ClassLoader cl) {
184 dl 1.78 if (cl != null && ClassLoader.getSystemClassLoader() != cl)
185 dl 1.77 throw new SecurityException("setContextClassLoader");
186 dl 1.60 }
187 dl 1.83
188     @SuppressWarnings("removal")
189     static AccessControlContext createACC() {
190     return new AccessControlContext(
191     new ProtectionDomain[] { new ProtectionDomain(null, null) });
192     }
193     static ThreadGroup createGroup() {
194     ThreadGroup group = Thread.currentThread().getThreadGroup();
195     for (ThreadGroup p; (p = group.getParent()) != null; )
196     group = p;
197     return new ThreadGroup(group, "InnocuousForkJoinWorkerThreadGroup");
198     }
199     static {
200     @SuppressWarnings("removal")
201     SecurityManager sm = System.getSecurityManager();
202     @SuppressWarnings("removal")
203     ThreadGroup g = innocuousThreadGroup =
204     (sm == null) ? createGroup() :
205     AccessController.doPrivileged(new PrivilegedAction<>() {
206     public ThreadGroup run() {
207     return createGroup(); }});
208     @SuppressWarnings("removal")
209     AccessControlContext a = innocuousACC =
210     (sm == null) ? createACC() :
211     AccessController.doPrivileged(new PrivilegedAction<>() {
212     public AccessControlContext run() {
213     return createACC(); }});
214     }
215 jsr166 1.1 }
216     }