/* Copyright (c) 2006, Sriram Srinivasan
*
* You may distribute this software under the terms of the license
* specified in the file "License"
*/
package kilim;
import java.util.concurrent.atomic.AtomicInteger;
public class WorkerThread extends Thread {
volatile Task runningTask;
/**
* A list of tasks that prefer to run only on this thread. This is used by kilim.ReentrantLock and Task to ensure
* that lock.release() is done on the same thread as lock.acquire()
*/
RingQueue<Task> tasks = new RingQueue<Task>(10);
Scheduler scheduler;
static AtomicInteger gid = new AtomicInteger();
public int numResumes = 0;
WorkerThread(Scheduler ascheduler) {
super("KilimWorker-" + gid.incrementAndGet());
scheduler = ascheduler;
}
public void run() {
try {
while (true) {
Task t = getNextTask(this); // blocks until task available
runningTask = t;
t._runExecute(this);
runningTask = null;
}
} catch (ShutdownException se) {
// nothing to do.
} catch (OutOfMemoryError ex) {
System.err.println("Out of memory");
System.exit(1);
} catch (Throwable ex) {
ex.printStackTrace();
System.err.println(runningTask);
}
runningTask = null;
}
protected Task getNextTask(WorkerThread workerThread) throws ShutdownException {
Task t = null;
while (true) {
if (scheduler.isShutdown())
throw new ShutdownException();
t = getNextTask();
if (t != null)
break;
// try loading from scheduler
scheduler.loadNextTask(this);
synchronized (this) { // ///////////////////////////////////////
// Wait if still no task to execute.
t = tasks.get();
if (t != null)
break;
scheduler.addWaitingThread(this);
try {
wait();
} catch (InterruptedException ignore) {
} // shutdown indicator checked above
} // //////////////////////////////////////////////////////////
}
assert t != null : "Returning null task";
return t;
}
public Task getCurrentTask() {
return runningTask;
}
public synchronized void addRunnableTask(Task t) {
assert t.preferredResumeThread == null || t.preferredResumeThread == this : "Task given to wrong thread";
tasks.put(t);
notify();
}
public synchronized boolean hasTasks() {
return tasks.size() > 0;
}
public synchronized Task getNextTask() {
return tasks.get();
}
public synchronized void waitForMsgOrSignal() {
try {
if (tasks.size() == 0) {
wait();
}
} catch (InterruptedException ignore) {
}
}
}