annotate dwtx/core/internal/jobs/WorkerPool.d @ 122:9d0585bcb7aa

Add core.jobs package
author Frank Benoit <benoit@tionex.de>
date Tue, 12 Aug 2008 02:34:21 +0200
parents
children 862b05e0334a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
122
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
1 /*******************************************************************************
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
2 * Copyright (c) 2003, 2007 IBM Corporation and others.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
3 * All rights reserved. This program and the accompanying materials
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
4 * are made available under the terms of the Eclipse Public License v1.0
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
5 * which accompanies this distribution, and is available at
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
6 * http://www.eclipse.org/legal/epl-v10.html
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
7 *
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
8 * Contributors:
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
9 * IBM - Initial API and implementation
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
10 * Port to the D programming language:
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
11 * Frank Benoit <benoit@tionex.de>
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
12 *******************************************************************************/
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
13 module dwtx.core.internal.jobs.WorkerPool;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
14
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
15 import tango.core.Thread;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
16 import tango.core.sync.Mutex;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
17 import tango.core.sync.Condition;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
18 import tango.text.convert.Format;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
19 import dwt.dwthelper.utils;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
20
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
21 import dwtx.core.runtime.Assert;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
22 import dwtx.core.runtime.IStatus;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
23 import dwtx.core.runtime.jobs.Job;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
24 import dwtx.core.internal.jobs.JobManager;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
25 import dwtx.core.internal.jobs.Worker;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
26
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
27 import dwtx.core.internal.jobs.InternalJob;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
28 import dwtx.core.internal.jobs.ThreadJob;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
29
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
30 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
31 * Maintains a pool of worker threads. Threads are constructed lazily as
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
32 * required, and are eventually discarded if not in use for awhile. This class
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
33 * maintains the thread creation/destruction policies for the job manager.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
34 *
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
35 * Implementation note: all the data structures of this class are protected
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
36 * by the instance's object monitor. To avoid deadlock with third party code,
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
37 * this lock is never held when calling methods outside this class that may in
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
38 * turn use locks.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
39 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
40 class WorkerPool {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
41
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
42 protected Mutex mutex;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
43 protected Condition condition;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
44
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
45
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
46 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
47 * Threads not used by their best before timestamp are destroyed.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
48 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
49 private static const int BEST_BEFORE = 60000;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
50 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
51 * There will always be at least MIN_THREADS workers in the pool.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
52 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
53 private static const int MIN_THREADS = 1;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
54 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
55 * Use the busy thread count to avoid starting new threads when a living
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
56 * thread is just doing house cleaning (notifying listeners, etc).
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
57 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
58 private int busyThreads = 0;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
59
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
60 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
61 * The default context class loader to use when creating worker threads.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
62 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
63 // protected const ClassLoader defaultContextLoader;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
64
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
65 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
66 * Records whether new worker threads should be daemon threads.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
67 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
68 private bool isDaemon = false;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
69
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
70 private JobManager manager;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
71 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
72 * The number of workers in the threads array
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
73 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
74 private int numThreads = 0;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
75 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
76 * The number of threads that are currently sleeping
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
77 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
78 private int sleepingThreads = 0;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
79 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
80 * The living set of workers in this pool.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
81 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
82 private Worker[] threads;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
83
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
84 protected package this(JobManager manager) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
85 threads = new Worker[10];
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
86 this.manager = manager;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
87 mutex = new Mutex;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
88 condition = new Condition(mutex);
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
89 // this.defaultContextLoader = Thread.currentThread().getContextClassLoader();
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
90 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
91
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
92 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
93 * Adds a worker to the list of workers.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
94 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
95 private void add(Worker worker) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
96 synchronized(mutex){
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
97 int size = threads.length;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
98 if (numThreads + 1 > size) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
99 Worker[] newThreads = new Worker[2 * size];
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
100 System.arraycopy(threads, 0, newThreads, 0, size);
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
101 threads = newThreads;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
102 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
103 threads[numThreads++] = worker;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
104 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
105 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
106
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
107 private void decrementBusyThreads() {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
108 synchronized(mutex){
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
109 //impossible to have less than zero busy threads
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
110 if (--busyThreads < 0) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
111 if (JobManager.DEBUG)
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
112 Assert.isTrue(false, Integer.toString(busyThreads));
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
113 busyThreads = 0;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
114 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
115 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
116 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
117
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
118 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
119 * Signals the end of a job. Note that this method can be called under
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
120 * OutOfMemoryError conditions and thus must be paranoid about allocating objects.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
121 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
122 protected void endJob(InternalJob job, IStatus result) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
123 decrementBusyThreads();
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
124 //need to end rule in graph before ending job so that 2 threads
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
125 //do not become the owners of the same rule in the graph
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
126 if ((job.getRule_package() !is null) && !(cast(ThreadJob)job )) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
127 //remove any locks this thread may be owning on that rule
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
128 manager.getLockManager().removeLockCompletely(Thread.getThis(), job.getRule_package());
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
129 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
130 manager.endJob_package(job, result, true);
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
131 //ensure this thread no longer owns any scheduling rules
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
132 manager.implicitJobs.endJob(job);
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
133 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
134 package void endJob_package(InternalJob job, IStatus result) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
135 endJob(job, result);
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
136 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
137
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
138 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
139 * Signals the death of a worker thread. Note that this method can be called under
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
140 * OutOfMemoryError conditions and thus must be paranoid about allocating objects.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
141 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
142 protected void endWorker(Worker worker) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
143 synchronized(mutex){
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
144 if (remove(worker) && JobManager.DEBUG)
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
145 JobManager.debug_(Format("worker removed from pool: {}", worker)); //$NON-NLS-1$
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
146 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
147 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
148 package void endWorker_package(Worker worker) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
149 endWorker(worker);
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
150 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
151
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
152 private void incrementBusyThreads() {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
153 synchronized(mutex){
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
154 //impossible to have more busy threads than there are threads
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
155 if (++busyThreads > numThreads) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
156 if (JobManager.DEBUG)
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
157 Assert.isTrue(false, Format( "{},{}", busyThreads, numThreads));
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
158 busyThreads = numThreads;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
159 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
160 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
161 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
162
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
163 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
164 * Notification that a job has been added to the queue. Wake a worker,
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
165 * creating a new worker if necessary. The provided job may be null.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
166 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
167 protected package void jobQueued() {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
168 synchronized(mutex){
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
169 //if there is a sleeping thread, wake it up
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
170 if (sleepingThreads > 0) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
171 condition.notify();
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
172 return;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
173 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
174 //create a thread if all threads are busy
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
175 if (busyThreads >= numThreads) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
176 Worker worker = new Worker(this);
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
177 worker.isDaemon(isDaemon);
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
178 add(worker);
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
179 if (JobManager.DEBUG)
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
180 JobManager.debug_(Format("worker added to pool: {}", worker)); //$NON-NLS-1$
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
181 worker.start();
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
182 return;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
183 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
184 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
185 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
186
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
187 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
188 * Remove a worker thread from our list.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
189 * @return true if a worker was removed, and false otherwise.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
190 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
191 private bool remove(Worker worker) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
192 synchronized(mutex){
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
193 for (int i = 0; i < threads.length; i++) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
194 if (threads[i] is worker) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
195 System.arraycopy(threads, i + 1, threads, i, numThreads - i - 1);
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
196 threads[--numThreads] = null;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
197 return true;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
198 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
199 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
200 return false;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
201 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
202 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
203
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
204 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
205 * Sets whether threads created in the worker pool should be daemon threads.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
206 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
207 void setDaemon(bool value) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
208 this.isDaemon = value;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
209 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
210
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
211 protected void shutdown() {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
212 synchronized(mutex){
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
213 condition.notifyAll();
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
214 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
215 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
216 package void shutdown_package() {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
217 shutdown();
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
218 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
219
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
220 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
221 * Sleep for the given duration or until woken.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
222 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
223 private void sleep(long duration) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
224 synchronized(mutex){
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
225 sleepingThreads++;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
226 busyThreads--;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
227 if (JobManager.DEBUG)
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
228 JobManager.debug_(Format("worker sleeping for: {}ms", duration)); //$NON-NLS-1$ //$NON-NLS-2$
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
229 try {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
230 condition.wait(duration/1000.0f);
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
231 } catch (InterruptedException e) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
232 if (JobManager.DEBUG)
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
233 JobManager.debug_("worker interrupted while waiting... :-|"); //$NON-NLS-1$
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
234 } finally {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
235 sleepingThreads--;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
236 busyThreads++;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
237 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
238 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
239 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
240
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
241 /**
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
242 * Returns a new job to run. Returns null if the thread should die.
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
243 */
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
244 protected InternalJob startJob(Worker worker) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
245 //if we're above capacity, kill the thread
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
246 synchronized (mutex) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
247 if (!manager.isActive_package()) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
248 //must remove the worker immediately to prevent all threads from expiring
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
249 endWorker(worker);
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
250 return null;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
251 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
252 //set the thread to be busy now in case of reentrant scheduling
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
253 incrementBusyThreads();
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
254 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
255 Job job = null;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
256 try {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
257 job = manager.startJob_package();
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
258 //spin until a job is found or until we have been idle for too long
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
259 long idleStart = System.currentTimeMillis();
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
260 while (manager.isActive_package() && job is null) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
261 long hint = manager.sleepHint_package();
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
262 if (hint > 0)
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
263 sleep(Math.min(hint, BEST_BEFORE));
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
264 job = manager.startJob_package();
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
265 //if we were already idle, and there are still no new jobs, then
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
266 // the thread can expire
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
267 synchronized (mutex) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
268 if (job is null && (System.currentTimeMillis() - idleStart > BEST_BEFORE) && (numThreads - busyThreads) > MIN_THREADS) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
269 //must remove the worker immediately to prevent all threads from expiring
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
270 endWorker(worker);
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
271 return null;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
272 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
273 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
274 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
275 if (job !is null) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
276 //if this job has a rule, then we are essentially acquiring a lock
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
277 if ((job.getRule() !is null) && !(cast(ThreadJob)job )) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
278 //don't need to re-aquire locks because it was not recorded in the graph
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
279 //that this thread waited to get this rule
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
280 manager.getLockManager().addLockThread(Thread.getThis(), job.getRule());
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
281 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
282 //see if we need to wake another worker
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
283 if (manager.sleepHint_package() <= 0)
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
284 jobQueued();
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
285 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
286 } finally {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
287 //decrement busy thread count if we're not running a job
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
288 if (job is null)
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
289 decrementBusyThreads();
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
290 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
291 return job;
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
292 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
293 package InternalJob startJob_package(Worker worker) {
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
294 return startJob(worker);
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
295 }
9d0585bcb7aa Add core.jobs package
Frank Benoit <benoit@tionex.de>
parents:
diff changeset
296 }