|
Packit |
5e46da |
/*
|
|
Packit |
5e46da |
* This file is part of libbluray
|
|
Packit |
5e46da |
*
|
|
Packit |
5e46da |
* This library is free software; you can redistribute it and/or
|
|
Packit |
5e46da |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
5e46da |
* License as published by the Free Software Foundation; either
|
|
Packit |
5e46da |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
5e46da |
*
|
|
Packit |
5e46da |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
5e46da |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
5e46da |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
5e46da |
* Lesser General Public License for more details.
|
|
Packit |
5e46da |
*
|
|
Packit |
5e46da |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
5e46da |
* License along with this library. If not, see
|
|
Packit |
5e46da |
* <http://www.gnu.org/licenses/>.
|
|
Packit |
5e46da |
*/
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
package org.videolan;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
import java.util.LinkedList;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
public class BDJActionQueue implements Runnable {
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
public static BDJActionQueue create(String name) {
|
|
Packit |
5e46da |
return create(null, name);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
public static BDJActionQueue create(BDJThreadGroup threadGroup, String name) {
|
|
Packit |
5e46da |
BDJActionQueue aq = new BDJActionQueue(threadGroup, name);
|
|
Packit |
5e46da |
aq.startThread(threadGroup, name);
|
|
Packit |
5e46da |
return aq;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
private BDJActionQueue(BDJThreadGroup threadGroup, String name) {
|
|
Packit |
5e46da |
if (threadGroup == null) {
|
|
Packit |
5e46da |
if (BDJXletContext.getCurrentContext() != null) {
|
|
Packit |
5e46da |
logger.error("BDJActionQueue " + name + " created from wrong context: " + Logger.dumpStack());
|
|
Packit |
5e46da |
// throw new SecurityException();
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
private void startThread(BDJThreadGroup threadGroup, String name) {
|
|
Packit |
5e46da |
/* run all actions in given thread group / xlet context */
|
|
Packit |
5e46da |
thread = new Thread(threadGroup, this, name + ".BDJActionQueue");
|
|
Packit |
5e46da |
thread.setDaemon(true);
|
|
Packit |
5e46da |
thread.start();
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
watchdog = new Watchdog();
|
|
Packit |
5e46da |
watchdog.start(name);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
public void shutdown() {
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
synchronized (actions) {
|
|
Packit |
5e46da |
terminated = true;
|
|
Packit |
5e46da |
actions.addLast(null);
|
|
Packit |
5e46da |
actions.notifyAll();
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
watchdog.shutdown();
|
|
Packit |
5e46da |
try {
|
|
Packit |
5e46da |
thread.join();
|
|
Packit |
5e46da |
} catch (InterruptedException t) {
|
|
Packit |
5e46da |
logger.error("Error joining thread: " + t);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
public void run() {
|
|
Packit |
5e46da |
while (true) {
|
|
Packit |
5e46da |
Object action;
|
|
Packit |
5e46da |
synchronized (actions) {
|
|
Packit |
5e46da |
while (actions.isEmpty()) {
|
|
Packit |
5e46da |
try {
|
|
Packit |
5e46da |
actions.wait();
|
|
Packit |
5e46da |
} catch (InterruptedException e) {
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
action = actions.removeFirst();
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if (action == null)
|
|
Packit |
5e46da |
return;
|
|
Packit |
5e46da |
try {
|
|
Packit |
5e46da |
watchdog.startAction(action);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
((BDJAction)action).process();
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
watchdog.endAction();
|
|
Packit |
5e46da |
} catch (ThreadDeath d) {
|
|
Packit |
5e46da |
System.err.println("action failed: " + d + "\n");
|
|
Packit |
5e46da |
throw d;
|
|
Packit |
5e46da |
} catch (Throwable e) {
|
|
Packit |
5e46da |
System.err.println("action failed: " + e + "\n" + Logger.dumpStack(e));
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
public void put(BDJAction action) {
|
|
Packit |
5e46da |
if (action != null) {
|
|
Packit |
5e46da |
synchronized (actions) {
|
|
Packit |
5e46da |
if (!terminated) {
|
|
Packit |
5e46da |
actions.addLast(action);
|
|
Packit |
5e46da |
actions.notifyAll();
|
|
Packit |
5e46da |
} else {
|
|
Packit |
5e46da |
logger.error("Action skipped (queue stopped): " + action);
|
|
Packit |
5e46da |
action.abort();
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
private boolean terminated = false;
|
|
Packit |
5e46da |
private Thread thread;
|
|
Packit |
5e46da |
private LinkedList actions = new LinkedList();
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
private static final Logger logger = Logger.getLogger(BDJActionQueue.class.getName());
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/*
|
|
Packit |
5e46da |
*
|
|
Packit |
5e46da |
*/
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
private Watchdog watchdog = null;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
class Watchdog implements Runnable {
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
private Object currentAction = null;
|
|
Packit |
5e46da |
private boolean terminate = false;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
Watchdog() {}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
synchronized void start(String name) {
|
|
Packit |
5e46da |
Thread t = new Thread(null, this, name + ".BDJActionQueue.Monitor");
|
|
Packit |
5e46da |
t.setDaemon(true);
|
|
Packit |
5e46da |
t.start();
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
public synchronized void shutdown() {
|
|
Packit |
5e46da |
terminate = true;
|
|
Packit |
5e46da |
notifyAll();
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
public synchronized void startAction(Object action) {
|
|
Packit |
5e46da |
currentAction = action;
|
|
Packit |
5e46da |
notifyAll();
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
public synchronized void endAction() {
|
|
Packit |
5e46da |
currentAction = null;
|
|
Packit |
5e46da |
notifyAll();
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
public void run() {
|
|
Packit |
5e46da |
Object loggedAction = null;
|
|
Packit |
5e46da |
synchronized (this) {
|
|
Packit |
5e46da |
while (!terminate) {
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (loggedAction != null && currentAction != loggedAction) {
|
|
Packit |
5e46da |
loggedAction = null;
|
|
Packit |
5e46da |
logger.info("Callback returned (" + thread + ")");
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
try {
|
|
Packit |
5e46da |
if (currentAction == null) {
|
|
Packit |
5e46da |
wait();
|
|
Packit |
5e46da |
} else {
|
|
Packit |
5e46da |
Object cachedAction = currentAction;
|
|
Packit |
5e46da |
wait(5000);
|
|
Packit |
5e46da |
if (currentAction == cachedAction && loggedAction != cachedAction) {
|
|
Packit |
5e46da |
logger.error("Callback timeout in " + thread + ", callback=" + currentAction + "\n" +
|
|
Packit |
5e46da |
PortingHelper.dumpStack(thread));
|
|
Packit |
5e46da |
loggedAction = cachedAction;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
} catch (InterruptedException e) {
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|