01: /*
02: * This is free software, licensed under the Gnu Public License (GPL)
03: * get a copy from <http://www.gnu.org/licenses/gpl.html>
04: *
05: * author: Henner Zeller <H.Zeller@acm.org>
06: */
07: package henplus.commands;
08:
09: import henplus.Interruptable;
10:
11: /**
12: * A thread to be used to cancel a statement running
13: * in another thread.
14: */
15: final class StatementCanceller implements Runnable, Interruptable {
16: private final CancelTarget _target;
17: private boolean _armed;
18: private boolean _running;
19: private volatile boolean _cancelStatement;
20:
21: /**
22: * The target to be cancelled. Must not throw an Execption
23: * and may to whatever it needs to do.
24: */
25: public interface CancelTarget {
26: void cancelRunningStatement();
27: }
28:
29: public StatementCanceller(CancelTarget target) {
30: _cancelStatement = false;
31: _armed = false;
32: _running = true;
33: _target = target;
34: }
35:
36: /** inherited: interruptable interface */
37: public void interrupt() {
38: _cancelStatement = true;
39: /* watch out, we must not call notify, since we
40: * are in the midst of a signal handler */
41: }
42:
43: public synchronized void stopThread() {
44: _running = false;
45: notify();
46: }
47:
48: public synchronized void arm() {
49: _armed = true;
50: _cancelStatement = false;
51: notify();
52: }
53:
54: public synchronized void disarm() {
55: _armed = false;
56: _cancelStatement = false;
57: notify();
58: }
59:
60: public synchronized void run() {
61: try {
62: for (;;) {
63: while (_running && !_armed) {
64: wait();
65: }
66: if (!_running)
67: return;
68: while (_armed && !_cancelStatement) {
69: wait(300);
70: }
71: if (_cancelStatement) {
72: try {
73: _target.cancelRunningStatement();
74: } catch (Exception e) {
75: /* ignore */
76: }
77: _armed = false;
78: }
79: }
80: } catch (InterruptedException e) {
81: return;
82: }
83: }
84: }
|