ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ForkJoinWorkerThread.java
Revision: 1.77
Committed: Thu Dec 13 14:17:33 2018 UTC (5 years, 5 months ago) by dl
Branch: MAIN
Changes since 1.76: +2 -1 lines
Log Message:
don't throw needless exception in InnocuousForkJoinWorkerThread.setContextClassLoader

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 dl 1.60 import java.security.AccessControlContext;
10 jsr166 1.74 import java.security.AccessController;
11     import java.security.PrivilegedAction;
12 dl 1.60 import java.security.ProtectionDomain;
13    
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     * This class just maintains links to its pool and WorkQueue. The
37 dl 1.56 * pool field is set immediately upon construction, but the
38     * workQueue field is not set until a call to registerWorker
39     * completes. This leads to a visibility race, that is tolerated
40     * by requiring that the workQueue field is only accessed by the
41     * owning thread.
42 dl 1.60 *
43     * Support for (non-public) subclass InnocuousForkJoinWorkerThread
44 dl 1.70 * requires that we break quite a lot of encapsulation (via helper
45 jsr166 1.72 * methods in ThreadLocalRandom) both here and in the subclass to
46 dl 1.70 * access and set Thread fields.
47 jsr166 1.1 */
48    
49 dl 1.52 final ForkJoinPool pool; // the pool this thread works in
50 dl 1.56 final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics
51 dl 1.54
52     /**
53 jsr166 1.1 * Creates a ForkJoinWorkerThread operating in the given pool.
54     *
55     * @param pool the pool this thread works in
56     * @throws NullPointerException if pool is null
57     */
58     protected ForkJoinWorkerThread(ForkJoinPool pool) {
59 dl 1.56 // Use a placeholder until a useful name can be set in registerWorker
60     super("aForkJoinWorkerThread");
61 dl 1.55 this.pool = pool;
62 dl 1.56 this.workQueue = pool.registerWorker(this);
63 dl 1.14 }
64    
65 jsr166 1.1 /**
66 jsr166 1.74 * Version for use by the default pool. Supports setting the
67     * context class loader. This is a separate constructor to avoid
68     * affecting the protected constructor.
69     */
70     ForkJoinWorkerThread(ForkJoinPool pool, ClassLoader ccl) {
71     super("aForkJoinWorkerThread");
72     super.setContextClassLoader(ccl);
73     this.pool = pool;
74     this.workQueue = pool.registerWorker(this);
75     }
76    
77     /**
78 jsr166 1.68 * Version for InnocuousForkJoinWorkerThread.
79 dl 1.60 */
80 jsr166 1.74 ForkJoinWorkerThread(ForkJoinPool pool,
81     ClassLoader ccl,
82     ThreadGroup threadGroup,
83 dl 1.60 AccessControlContext acc) {
84     super(threadGroup, null, "aForkJoinWorkerThread");
85 jsr166 1.74 super.setContextClassLoader(ccl);
86 jsr166 1.71 ThreadLocalRandom.setInheritedAccessControlContext(this, acc);
87 dl 1.70 ThreadLocalRandom.eraseThreadLocals(this); // clear before registering
88 dl 1.60 this.pool = pool;
89     this.workQueue = pool.registerWorker(this);
90     }
91    
92     /**
93 jsr166 1.1 * Returns the pool hosting this thread.
94     *
95     * @return the pool
96     */
97     public ForkJoinPool getPool() {
98     return pool;
99     }
100    
101     /**
102 jsr166 1.59 * Returns the unique index number of this thread in its pool.
103     * The returned value ranges from zero to the maximum number of
104     * threads (minus one) that may exist in the pool, and does not
105     * change during the lifetime of the thread. This method may be
106     * useful for applications that track status or collect results
107     * per-worker-thread rather than per-task.
108 jsr166 1.1 *
109     * @return the index number
110     */
111     public int getPoolIndex() {
112 dl 1.65 return workQueue.getPoolIndex();
113 dl 1.45 }
114    
115 jsr166 1.1 /**
116 dl 1.14 * Initializes internal state after construction but before
117     * processing any tasks. If you override this method, you must
118 jsr166 1.39 * invoke {@code super.onStart()} at the beginning of the method.
119 dl 1.14 * Initialization requires care: Most fields must have legal
120     * default values, to ensure that attempted accesses from other
121     * threads work correctly even before this thread starts
122     * processing tasks.
123 jsr166 1.1 */
124 dl 1.14 protected void onStart() {
125     }
126 jsr166 1.1
127     /**
128 dl 1.14 * Performs cleanup associated with termination of this worker
129     * thread. If you override this method, you must invoke
130     * {@code super.onTermination} at the end of the overridden method.
131 jsr166 1.4 *
132 dl 1.14 * @param exception the exception causing this thread to abort due
133     * to an unrecoverable error, or {@code null} if completed normally
134 jsr166 1.1 */
135 dl 1.14 protected void onTermination(Throwable exception) {
136 jsr166 1.1 }
137    
138     /**
139     * This method is required to be public, but should never be
140     * called explicitly. It performs the main run loop to execute
141 jsr166 1.40 * {@link ForkJoinTask}s.
142 jsr166 1.1 */
143     public void run() {
144 dl 1.60 if (workQueue.array == null) { // only run once
145     Throwable exception = null;
146 dl 1.52 try {
147 dl 1.60 onStart();
148     pool.runWorker(workQueue);
149 dl 1.52 } catch (Throwable ex) {
150 dl 1.60 exception = ex;
151 dl 1.52 } finally {
152 dl 1.60 try {
153     onTermination(exception);
154     } catch (Throwable ex) {
155     if (exception == null)
156     exception = ex;
157     } finally {
158     pool.deregisterWorker(this, exception);
159     }
160     }
161     }
162     }
163    
164     /**
165 jsr166 1.68 * Non-public hook method for InnocuousForkJoinWorkerThread.
166 dl 1.60 */
167     void afterTopLevelExec() {
168     }
169    
170     /**
171     * A worker thread that has no permissions, is not a member of any
172 jsr166 1.74 * user-defined ThreadGroup, uses the system class loader as
173     * thread context class loader, and erases all ThreadLocals after
174 dl 1.60 * running each top-level task.
175     */
176     static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread {
177     /** The ThreadGroup for all InnocuousForkJoinWorkerThreads */
178     private static final ThreadGroup innocuousThreadGroup =
179 jsr166 1.75 AccessController.doPrivileged(new PrivilegedAction<>() {
180     public ThreadGroup run() {
181     ThreadGroup group = Thread.currentThread().getThreadGroup();
182     for (ThreadGroup p; (p = group.getParent()) != null; )
183     group = p;
184     return new ThreadGroup(
185     group, "InnocuousForkJoinWorkerThreadGroup");
186     }});
187 dl 1.60
188     /** An AccessControlContext supporting no privileges */
189     private static final AccessControlContext INNOCUOUS_ACC =
190     new AccessControlContext(
191 jsr166 1.75 new ProtectionDomain[] { new ProtectionDomain(null, null) });
192 dl 1.60
193     InnocuousForkJoinWorkerThread(ForkJoinPool pool) {
194 jsr166 1.74 super(pool,
195     ClassLoader.getSystemClassLoader(),
196     innocuousThreadGroup,
197     INNOCUOUS_ACC);
198 dl 1.60 }
199    
200     @Override // to erase ThreadLocals
201     void afterTopLevelExec() {
202 dl 1.70 ThreadLocalRandom.eraseThreadLocals(this);
203 dl 1.60 }
204    
205     @Override // to silently fail
206     public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) { }
207    
208     @Override // paranoically
209     public void setContextClassLoader(ClassLoader cl) {
210 dl 1.77 if (cl != null && !ClassLoader.getSystemClassLoader().equals(cl))
211     throw new SecurityException("setContextClassLoader");
212 dl 1.60 }
213 jsr166 1.1 }
214     }