feisty meow concerns codebase 2.140
ethread.java
Go to the documentation of this file.
1package org.feistymeow.process;
2
3import org.apache.commons.logging.Log;
4import org.apache.commons.logging.LogFactory;
5
14public abstract class ethread implements Runnable
15{
16 private static Log c_logger = LogFactory.getLog(ethread.class);
17
18 // the actual java thread object.
19 private volatile Thread c_RealThread = null;
20 // provides synchronization for the thread.
21 private volatile Object c_lock = new Object();
22 // this is the timing period, for a timed thread. if zero, then this is a single shot thread.
23 private long c_period = 0;
24 // records whether the thread should shut down or not.
25 private boolean c_stopThread = false;
26 // snooze between checks on the stop timer.
27 final long SNOOZE_PERIOD = 20;
28
32 public ethread()
33 {
34 }
35
40 public ethread(long period)
41 {
42 c_period = period;
43 }
44
51 abstract public boolean performActivity();
52
56 public void start()
57 {
58 synchronized (c_lock) {
59 if (null == this.c_RealThread) {
60 this.c_RealThread = new Thread(this);
61 c_logger.debug("starting thread " + c_RealThread.getId());
62 this.c_RealThread.start();
63 }
64 }
65 }
66
70 public void stop()
71 {
72 cancel();
73 while (true) {
74 if (threadAlive()) {
75 try {
76 Thread.sleep(40);
77 } catch (InterruptedException e) {
78 // ignoring this since we'll keep snoozing as needed.
79 }
80 } else {
81 break;
82 }
83 }
84 }
85
89 void cancel()
90 {
91 synchronized (c_lock) {
92 c_stopThread = true;
93 Thread goAway = c_RealThread;
94 c_RealThread = null;
95 if (null != goAway) {
96 goAway.interrupt();
97 }
98 }
99 }
100
104 public boolean threadAlive()
105 {
106 synchronized (c_lock) {
107 return this.c_RealThread != null;
108 }
109 }
110
114 public boolean shouldStop()
115 {
116 synchronized (c_lock) {
117 return c_stopThread;
118 }
119 }
120
125 @Override
126 public void run()
127 {
128 if (!threadAlive()) {
129 return; // stopped before it ever started. how can this be? we just got invoked.
130 }
131 try {
132 while (true) {
133 boolean keepGoing = performActivity();
134 if (!keepGoing) {
135 c_logger.debug("thread returned false, signifying it wants to exit. now dropping it.");
136 break;
137 }
138 if (c_period == 0) {
139 // not a periodic thread, so we're done now.
140 break;
141 }
142 long nextRun = System.currentTimeMillis() + c_period;
143 while (System.currentTimeMillis() < nextRun) {
144 if (shouldStop()) {
145 break;
146 }
147 try {
148 Thread.sleep(SNOOZE_PERIOD);
149 } catch (InterruptedException e) {
150 // well, we'll hit it again soon.
151 }
152 }
153 }
154 } catch (Throwable t) {
155 c_logger.info("exception thrown from performActivity: " + t.getLocalizedMessage(), t);
156 }
157 // reset the thread held since we're leaving right now.
158 c_stopThread = true;
159 c_RealThread = null;
160 }
161}
abstract boolean performActivity()