/*
* @(#)LoopThread.java 1.12 02/08/21
*
* Copyright (c) 1996-2002 Sun Microsystems, Inc. All rights reserved.
*/
package com.sun.media.util;
/**
* LoopThread
* A looping thread that implements a safe way of pausing and restarting.
* Instead of using suspend() and resume() from the thread class, a pause()
* and start() method is provided.
* To use it, you will:
* - subclass from it;
* - overwrite the process() callback;
* - call start() to initiate the thread.
* @version 1.9, 98/09/28
*/
public abstract class LoopThread extends MediaThread {
protected boolean paused = false, started = false;
protected boolean killed = false;
private boolean waitingAtPaused = false;
/**
* The pause flag determines the initial state.
*/
public LoopThread() {
setName("Loop thread");
}
/**
* Set the paused state to true. The thread will halt at the
* beginning of the loop at the next iteration. i.e., unlike
* suspend(), the thread will NOT pause immediately. It will execute
* until the next waitHereIfPaused() is encountered.
*/
public synchronized void pause() {
paused = true;
}
/**
* Same as pause except that it blocks until the loop has actually
* paused (at waitHereIfPaused).
*/
public synchronized void blockingPause() {
if (waitingAtPaused || killed) return;
paused = true;
waitForCompleteStop();
}
public boolean isPaused() {
return paused;
}
/**
* Wait until the loop has come to a complete stop.
*/
public synchronized void waitForCompleteStop() {
try {
while (!killed && !waitingAtPaused && paused)
wait();
} catch (InterruptedException e) { }
}
/**
* Wait until the loop has come to a complete stop.
* Time out after the given milli seconds.
*/
public synchronized void waitForCompleteStop(int millis) {
try {
if (!killed && !waitingAtPaused && paused)
wait(millis);
} catch (InterruptedException e) { }
}
/**
* Resume the loop at the beginning of the loop where
* waitHereIfPaused() is called.
*/
public synchronized void start() {
if (!started) {
super.start();
started = true;
}
paused = false;
notifyAll();
}
public synchronized void kill() {
killed = true;
notifyAll();
}
/**
* Put the thread in a wait() if the paused state is on. Otherwise, it
* will just proceed.
*/
public synchronized boolean waitHereIfPaused() {
if (killed)
return false;
waitingAtPaused = true;
if (paused)
notifyAll(); // notify the blocking pause.
try {
while (!killed && paused)
wait();
} catch (InterruptedException e) {
System.err.println("Timer: timeLoop() wait interrupted " + e);
}
waitingAtPaused = false;
if (killed)
return false;
return true;
}
/**
* process callback function.
*/
protected abstract boolean process();
/**
* The run method for the Thread class.
*/
public void run() {
for (;;) {
// Wait here if pause() was invoked. Until start() is called,
// the thread will wait here indefinitely.
if (!waitHereIfPaused())
break;
// Invoke the callback function.
if (!process())
break;
}
}
}
|