1a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson/*
229957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
329957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer *
429957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * This code is free software; you can redistribute it and/or modify it
529957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * under the terms of the GNU General Public License version 2 only, as
629957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * published by the Free Software Foundation.  Oracle designates this
729957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * particular file as subject to the "Classpath" exception as provided
829957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * by Oracle in the LICENSE file that accompanied this code.
929957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer *
1029957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * This code is distributed in the hope that it will be useful, but WITHOUT
1129957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1229957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1329957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * version 2 for more details (a copy is included in the LICENSE file that
1429957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * accompanied this code).
1529957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer *
1629957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * You should have received a copy of the GNU General Public License version
1729957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * 2 along with this work; if not, write to the Free Software Foundation,
1829957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1929957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer *
2029957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2129957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * or visit www.oracle.com if you need additional information or have any
2229957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * questions.
2329957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer */
2429957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer
2529957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer/*
2629957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * This file is available under and governed by the GNU General Public
2729957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * License version 2 only, as published by the Free Software Foundation.
2829957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * However, the following notice accompanied the original version of this
2929957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer * file:
3029957558cf0db700bfaae360a80c42dc3871d0e5Tobias Thierer *
31a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * Written by Doug Lea with assistance from members of JCP JSR-166
32a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * Expert Group and released to the public domain, as explained at
33a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * http://creativecommons.org/publicdomain/zero/1.0/
34a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson */
35a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
36a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilsonpackage java.util.concurrent;
37a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
38b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniakimport java.security.AccessControlContext;
39b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniakimport java.security.ProtectionDomain;
40b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak
41a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson/**
42a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * A thread managed by a {@link ForkJoinPool}, which executes
43a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * {@link ForkJoinTask}s.
44a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * This class is subclassable solely for the sake of adding
45a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * functionality -- there are no overridable methods dealing with
46a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * scheduling or execution.  However, you can override initialization
47a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * and termination methods surrounding the main task processing loop.
48a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * If you do create such a subclass, you will also need to supply a
4975a06e56a4cc4599946e21422513e4bafa759509Calin Juravle * custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to
5075a06e56a4cc4599946e21422513e4bafa759509Calin Juravle * {@linkplain ForkJoinPool#ForkJoinPool use it} in a {@code ForkJoinPool}.
51a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson *
52a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * @since 1.7
53a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * @author Doug Lea
54a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson */
55a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilsonpublic class ForkJoinWorkerThread extends Thread {
56a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    /*
57a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * ForkJoinWorkerThreads are managed by ForkJoinPools and perform
5891770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * ForkJoinTasks. For explanation, see the internal documentation
5991770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * of class ForkJoinPool.
60a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     *
6191770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * This class just maintains links to its pool and WorkQueue.  The
6291770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * pool field is set immediately upon construction, but the
6391770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * workQueue field is not set until a call to registerWorker
6491770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * completes. This leads to a visibility race, that is tolerated
6591770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * by requiring that the workQueue field is only accessed by the
6691770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * owning thread.
67b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak     *
68b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak     * Support for (non-public) subclass InnocuousForkJoinWorkerThread
69b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak     * requires that we break quite a lot of encapsulation (via Unsafe)
70b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak     * both here and in the subclass to access and set Thread fields.
71a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     */
72a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
7391770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle    final ForkJoinPool pool;                // the pool this thread works in
7491770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle    final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics
75a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
76a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    /**
77a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * Creates a ForkJoinWorkerThread operating in the given pool.
78a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     *
79a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * @param pool the pool this thread works in
80a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * @throws NullPointerException if pool is null
81a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     */
82a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    protected ForkJoinWorkerThread(ForkJoinPool pool) {
8391770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        // Use a placeholder until a useful name can be set in registerWorker
8491770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        super("aForkJoinWorkerThread");
85a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        this.pool = pool;
8691770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        this.workQueue = pool.registerWorker(this);
87a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    }
88a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
89a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    /**
90b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak     * Version for InnocuousForkJoinWorkerThread.
91b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak     */
92b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup,
93b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                         AccessControlContext acc) {
94b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        super(threadGroup, null, "aForkJoinWorkerThread");
95b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        U.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, acc);
96b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        eraseThreadLocals(); // clear before registering
97b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        this.pool = pool;
98b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        this.workQueue = pool.registerWorker(this);
99b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    }
100b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak
101b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    /**
102a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * Returns the pool hosting this thread.
103a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     *
104a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * @return the pool
105a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     */
106a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    public ForkJoinPool getPool() {
107a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        return pool;
108a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    }
109a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
110a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    /**
11175a06e56a4cc4599946e21422513e4bafa759509Calin Juravle     * Returns the unique index number of this thread in its pool.
11275a06e56a4cc4599946e21422513e4bafa759509Calin Juravle     * The returned value ranges from zero to the maximum number of
11375a06e56a4cc4599946e21422513e4bafa759509Calin Juravle     * threads (minus one) that may exist in the pool, and does not
11475a06e56a4cc4599946e21422513e4bafa759509Calin Juravle     * change during the lifetime of the thread.  This method may be
11575a06e56a4cc4599946e21422513e4bafa759509Calin Juravle     * useful for applications that track status or collect results
11675a06e56a4cc4599946e21422513e4bafa759509Calin Juravle     * per-worker-thread rather than per-task.
117a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     *
118a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * @return the index number
119a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     */
120a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    public int getPoolIndex() {
121b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        return workQueue.getPoolIndex();
122a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    }
123a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
124a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    /**
125a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * Initializes internal state after construction but before
126a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * processing any tasks. If you override this method, you must
127a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * invoke {@code super.onStart()} at the beginning of the method.
128a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * Initialization requires care: Most fields must have legal
129a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * default values, to ensure that attempted accesses from other
130a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * threads work correctly even before this thread starts
131a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * processing tasks.
132a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     */
133a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    protected void onStart() {
134a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    }
135a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
136a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    /**
137a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * Performs cleanup associated with termination of this worker
138a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * thread.  If you override this method, you must invoke
139a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * {@code super.onTermination} at the end of the overridden method.
140a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     *
141a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * @param exception the exception causing this thread to abort due
142a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * to an unrecoverable error, or {@code null} if completed normally
143a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     */
144a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    protected void onTermination(Throwable exception) {
145a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    }
146a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
147a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    /**
148a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * This method is required to be public, but should never be
149a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * called explicitly. It performs the main run loop to execute
150a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * {@link ForkJoinTask}s.
151a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     */
152a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    public void run() {
153b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        if (workQueue.array == null) { // only run once
154b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak            Throwable exception = null;
15591770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            try {
156b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                onStart();
157b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                pool.runWorker(workQueue);
15891770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            } catch (Throwable ex) {
159b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                exception = ex;
16091770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            } finally {
161b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                try {
162b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                    onTermination(exception);
163b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                } catch (Throwable ex) {
164b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                    if (exception == null)
165b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                        exception = ex;
166b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                } finally {
167b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                    pool.deregisterWorker(this, exception);
168b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                }
169b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak            }
170b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        }
171b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    }
172b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak
173b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    /**
174b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak     * Erases ThreadLocals by nulling out Thread maps.
175b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak     */
176b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    final void eraseThreadLocals() {
177b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        U.putObject(this, THREADLOCALS, null);
178b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        U.putObject(this, INHERITABLETHREADLOCALS, null);
179b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    }
180b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak
181b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    /**
182b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak     * Non-public hook method for InnocuousForkJoinWorkerThread.
183b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak     */
184b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    void afterTopLevelExec() {
185b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    }
186b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak
187b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    // Set up to allow setting thread fields in constructor
188b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
189b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    private static final long THREADLOCALS;
190b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    private static final long INHERITABLETHREADLOCALS;
191b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    private static final long INHERITEDACCESSCONTROLCONTEXT;
192b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    static {
193b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        try {
194b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak            THREADLOCALS = U.objectFieldOffset
195b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                (Thread.class.getDeclaredField("threadLocals"));
196b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak            INHERITABLETHREADLOCALS = U.objectFieldOffset
197b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                (Thread.class.getDeclaredField("inheritableThreadLocals"));
198b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak            INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset
199b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                (Thread.class.getDeclaredField("inheritedAccessControlContext"));
200b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        } catch (ReflectiveOperationException e) {
201b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak            throw new Error(e);
202b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        }
203b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    }
204b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak
205b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    /**
206b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak     * A worker thread that has no permissions, is not a member of any
207b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak     * user-defined ThreadGroup, and erases all ThreadLocals after
208b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak     * running each top-level task.
209b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak     */
210b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak    static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread {
211b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        /** The ThreadGroup for all InnocuousForkJoinWorkerThreads */
212b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        private static final ThreadGroup innocuousThreadGroup =
213b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak            createThreadGroup();
214b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak
215b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        /** An AccessControlContext supporting no privileges */
216b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        private static final AccessControlContext INNOCUOUS_ACC =
217b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak            new AccessControlContext(
218b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                new ProtectionDomain[] {
219b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                    new ProtectionDomain(null, null)
220b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                });
221b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak
222b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        InnocuousForkJoinWorkerThread(ForkJoinPool pool) {
223b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak            super(pool, innocuousThreadGroup, INNOCUOUS_ACC);
224b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        }
225b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak
226b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        @Override // to erase ThreadLocals
227b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        void afterTopLevelExec() {
228b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak            eraseThreadLocals();
229b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        }
230b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak
231b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        @Override // to always report system loader
232b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        public ClassLoader getContextClassLoader() {
233b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak            return ClassLoader.getSystemClassLoader();
234b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        }
235b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak
236b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        @Override // to silently fail
237b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) { }
238b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak
239b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        @Override // paranoically
240b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        public void setContextClassLoader(ClassLoader cl) {
241b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak            throw new SecurityException("setContextClassLoader");
242b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        }
243b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak
244b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        /**
245b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak         * Returns a new group with the system ThreadGroup (the
246b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak         * topmost, parent-less group) as parent.  Uses Unsafe to
247b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak         * traverse Thread.group and ThreadGroup.parent fields.
248b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak         */
249b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak        private static ThreadGroup createThreadGroup() {
250b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak            try {
251b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                sun.misc.Unsafe u = sun.misc.Unsafe.getUnsafe();
252b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                long tg = u.objectFieldOffset
253b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                    (Thread.class.getDeclaredField("group"));
254b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                long gp = u.objectFieldOffset
255b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                    (ThreadGroup.class.getDeclaredField("parent"));
256b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                ThreadGroup group = (ThreadGroup)
257b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                    u.getObject(Thread.currentThread(), tg);
258b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                while (group != null) {
259b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                    ThreadGroup parent = (ThreadGroup)u.getObject(group, gp);
260b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                    if (parent == null)
261b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                        return new ThreadGroup(group,
262b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                                               "InnocuousForkJoinWorkerThreadGroup");
263b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                    group = parent;
264b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                }
265b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak            } catch (ReflectiveOperationException e) {
266b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak                throw new Error(e);
267a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson            }
268b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak            // fall through if null as cannot-happen safeguard
269b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak            throw new Error("Cannot create ThreadGroup");
270a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        }
271a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    }
272b8b75116273ecfdb8ffdd1869b1c0dd04570a95ePrzemyslaw Szczepaniak
273a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson}
274