Files
mercury/java/runtime/Task.java
Paul Bone a2879c6837 Make MercuryThreadPool (java) notice when a thread blocks on a semaphore.
If threads are blocked while there is work in the queue extra threads may be
spawned to keep the processors busy.

Beginning now, tasks created with thread.spawn are use the thread pool.
(thread.spawn_native does not use the thread pool.)

java/runtime/Semaphore.java:
    Wrap Java's Semaphore class which call the current thread's blocked()
    and running() methods when a thread blocks and then runs after being
    blocked.

library/thread.semaphore.m:
    Use our own Semaphore class.

java/runtime/MercuryThread.java:
java/runtime/MercuryWorkerThread.java:
    Define blocked() and running() on our threads.

java/runtime/NativeThread.java:
    This class is used by spawn_native/4 and is required to define blocked()
    and running(), however it implements them as no-ops as it isn't included
    in the thread pool.

java/runtime/ThreadStatus.java:
    Define the BLOCKED status.

java/runtime/MercuryThreadPool.java:
    Count blocked threads seperatly and allow the creation of new threads
    when existing threads become blocked.

    Add some tracing code to help debug the thread management code.  This is
    disabled by default.

library/thread.m:
    Implement spawn for Java using the thread pool.  This was not enabled
    earlier because without using java/runtime/Semaphore.java it was
    possible to deadlock the system.

java/runtime/Task.java:
    Add some tracing code to debug thread state changes, this is disabled by
    default.
2014-10-03 19:22:32 +10:00

87 lines
1.9 KiB
Java

//
// Copyright (C) 2014 The Mercury Team
// This file may only be copied under the terms of the GNU Library General
// Public License - see the file COPYING.LIB in the Mercury distribution.
//
package jmercury.runtime;
/**
* Task is a task being managed by MercuryThreadPool.
* Callers can use this object to wait for the task's completion.
*/
public class Task implements Runnable
{
private static long next_id;
private long id;
private Runnable target;
private Status status;
public enum Status {
NEW,
SCHEDULED,
RUNNING,
FINISHED
}
/**
* Create a new task.
*/
public Task(Runnable target) {
id = allocateTaskId();
this.target = target;
status = Status.NEW;
}
private static synchronized long allocateTaskId() {
return next_id++;
}
public void run() {
updateStatus(Status.RUNNING);
target.run();
updateStatus(Status.FINISHED);
}
public long getId() {
return id;
}
public void scheduled() {
updateStatus(Status.SCHEDULED);
}
/**
* Update the task's status and notify any threads waiting on the
* status change.
*/
protected synchronized void updateStatus(Status status) {
if (MercuryThreadPool.debug) {
System.err.println("Thread: " + Thread.currentThread() +
"task: " + this + " status " + status);
}
this.status = status;
notifyAll();
}
/**
* Wait for the task to complete.
* This waits on the task's monitor. Callers should not be holding any
* other monitors.
*/
public synchronized void waitForTask()
throws InterruptedException
{
while (status != Status.FINISHED) {
wait();
}
}
public String toString() {
return "Task " + id;
}
}