1a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson/*
2a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * Written by Doug Lea with assistance from members of JCP JSR-166
3a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * Expert Group and released to the public domain, as explained at
4a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * http://creativecommons.org/publicdomain/zero/1.0/
5a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson */
6a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
7a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilsonpackage java.util.concurrent;
8a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
9a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson/**
10a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * A thread managed by a {@link ForkJoinPool}, which executes
11a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * {@link ForkJoinTask}s.
12a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * This class is subclassable solely for the sake of adding
13a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * functionality -- there are no overridable methods dealing with
14a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * scheduling or execution.  However, you can override initialization
15a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * and termination methods surrounding the main task processing loop.
16a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * If you do create such a subclass, you will also need to supply a
1775a06e56a4cc4599946e21422513e4bafa759509Calin Juravle * custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to
1875a06e56a4cc4599946e21422513e4bafa759509Calin Juravle * {@linkplain ForkJoinPool#ForkJoinPool use it} in a {@code ForkJoinPool}.
19a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson *
20a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * @since 1.7
21a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * @author Doug Lea
22a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson */
23a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilsonpublic class ForkJoinWorkerThread extends Thread {
24a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    /*
25a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * ForkJoinWorkerThreads are managed by ForkJoinPools and perform
2691770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * ForkJoinTasks. For explanation, see the internal documentation
2791770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * of class ForkJoinPool.
28a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     *
2991770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * This class just maintains links to its pool and WorkQueue.  The
3091770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * pool field is set immediately upon construction, but the
3191770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * workQueue field is not set until a call to registerWorker
3291770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * completes. This leads to a visibility race, that is tolerated
3391770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * by requiring that the workQueue field is only accessed by the
3491770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * owning thread.
35a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     */
36a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
3791770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle    final ForkJoinPool pool;                // the pool this thread works in
3891770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle    final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics
39a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
40a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    /**
41a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * Creates a ForkJoinWorkerThread operating in the given pool.
42a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     *
43a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * @param pool the pool this thread works in
44a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * @throws NullPointerException if pool is null
45a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     */
46a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    protected ForkJoinWorkerThread(ForkJoinPool pool) {
4791770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        // Use a placeholder until a useful name can be set in registerWorker
4891770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        super("aForkJoinWorkerThread");
49a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        this.pool = pool;
5091770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle        this.workQueue = pool.registerWorker(this);
51a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    }
52a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
53a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    /**
54a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * Returns the pool hosting this thread.
55a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     *
56a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * @return the pool
57a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     */
58a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    public ForkJoinPool getPool() {
59a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        return pool;
60a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    }
61a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
62a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    /**
6375a06e56a4cc4599946e21422513e4bafa759509Calin Juravle     * Returns the unique index number of this thread in its pool.
6475a06e56a4cc4599946e21422513e4bafa759509Calin Juravle     * The returned value ranges from zero to the maximum number of
6575a06e56a4cc4599946e21422513e4bafa759509Calin Juravle     * threads (minus one) that may exist in the pool, and does not
6675a06e56a4cc4599946e21422513e4bafa759509Calin Juravle     * change during the lifetime of the thread.  This method may be
6775a06e56a4cc4599946e21422513e4bafa759509Calin Juravle     * useful for applications that track status or collect results
6875a06e56a4cc4599946e21422513e4bafa759509Calin Juravle     * per-worker-thread rather than per-task.
69a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     *
70a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * @return the index number
71a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     */
72a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    public int getPoolIndex() {
7375a06e56a4cc4599946e21422513e4bafa759509Calin Juravle        return workQueue.poolIndex >>> 1; // ignore odd/even tag bit
74a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    }
75a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
76a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    /**
77a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * Initializes internal state after construction but before
78a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * processing any tasks. If you override this method, you must
79a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * invoke {@code super.onStart()} at the beginning of the method.
80a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * Initialization requires care: Most fields must have legal
81a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * default values, to ensure that attempted accesses from other
82a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * threads work correctly even before this thread starts
83a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * processing tasks.
84a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     */
85a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    protected void onStart() {
86a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    }
87a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
88a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    /**
89a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * Performs cleanup associated with termination of this worker
90a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * thread.  If you override this method, you must invoke
91a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * {@code super.onTermination} at the end of the overridden method.
92a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     *
93a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * @param exception the exception causing this thread to abort due
94a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * to an unrecoverable error, or {@code null} if completed normally
95a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     */
96a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    protected void onTermination(Throwable exception) {
97a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    }
98a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
99a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    /**
100a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * This method is required to be public, but should never be
101a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * called explicitly. It performs the main run loop to execute
102a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * {@link ForkJoinTask}s.
103a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     */
104a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    public void run() {
105a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        Throwable exception = null;
106a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        try {
107a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson            onStart();
10891770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            pool.runWorker(workQueue);
109a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        } catch (Throwable ex) {
110a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson            exception = ex;
111a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        } finally {
11291770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            try {
11391770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle                onTermination(exception);
11491770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            } catch (Throwable ex) {
11591770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle                if (exception == null)
11691770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle                    exception = ex;
11791770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            } finally {
11891770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle                pool.deregisterWorker(this, exception);
119a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson            }
120a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        }
121a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    }
122a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson}
123