View Javadoc
1 /************************************************************ 2 * Copyright * 3 * Portions of this software are Copyright (c) 1993 - 2002, * 4 * Chad Z. Hower (Kudzu) and the Indy Pit Crew * 5 * - http://www.nevrona.com/Indy/ * 6 ************************************************************/ 7 8 /************************************************************ 9 * Copyright * 10 * Portions of this software are Copyright (c) 1993 - 2002, * 11 * Chad Z. Hower (Kudzu) and the Indy Pit Crew * 12 * - http://www.nevrona.com/Indy/ * 13 ************************************************************/ 14 package org.indy; 15 16 import java.util.ArrayList; 17 import java.util.Collection; 18 import java.util.Collections; 19 import java.util.Iterator; 20 21 22 /*** 23 * Provides the basis for Indy threading as used by {@link PeerThread} in {@link TCPServer}. 24 * 25 * 26 *@author OTG 27 *@version 1.0 28 *@see StopMode 29 *@see Priority 30 */ 31 public abstract class IndyThread implements Runnable { 32 /*** 33 * 34 */ 35 private Priority priority = Priority.NORMAL; 36 37 /*** 38 * 39 */ 40 private StopMode stopMode = StopMode.TERMINATE; 41 42 /*** 43 * 44 */ 45 private volatile Exception terminatingException; 46 47 /*** 48 * 49 */ 50 private volatile boolean stopped = true; 51 52 /*** 53 * 54 */ 55 private volatile boolean terminated = false; 56 57 /*** 58 * 59 */ 60 private final Object suspendLock = new Object(); 61 62 /*** 63 * 64 */ 65 protected final Thread threadImpl = new IndyThreadImpl(); 66 67 /*** 68 * 69 */ 70 private final ArrayList threadListeners = new ArrayList(); 71 72 /*** 73 * Description of the Field 74 */ 75 protected volatile boolean stopRequested; 76 77 /*** 78 * Constructor for the IdThread object 79 */ 80 public IndyThread() { 81 } 82 83 /*** 84 * Gets the stopped attribute of the IdThread object 85 * 86 *@return The stopped value 87 */ 88 public boolean isStopped() { 89 return stopped; 90 } 91 92 /*** 93 * 94 * @return 95 */ 96 protected Thread getThreadImpl() { 97 return threadImpl; 98 } 99 100 /*** 101 * Description of the Method 102 */ 103 public final void start() { 104 if (terminated) { 105 throw new IllegalStateException(); 106 } 107 108 if (!threadImpl.isAlive()) { 109 threadImpl.start(); 110 } 111 else if (stopped) { 112 resume(); 113 } 114 115 stopped = false; 116 } 117 118 /*** 119 * Description of the Method 120 */ 121 public final void stop() { 122 if (!stopped) { 123 if (stopMode == StopMode.TERMINATE) { 124 terminate(); 125 } 126 127 stopped = true; 128 } 129 } 130 131 /*** 132 * 133 */ 134 public void terminate() { 135 stopped = true; 136 terminated = true; 137 resume(); 138 } 139 140 /*** 141 * 142 */ 143 private void resume() { 144 synchronized (suspendLock) { 145 suspendLock.notifyAll(); 146 } 147 } 148 149 /*** 150 * 151 * @throws InterruptedException 152 */ 153 private void suspend() throws InterruptedException { 154 synchronized (suspendLock) { 155 suspendLock.wait(); 156 } 157 } 158 159 /*** 160 * Description of the Method 161 * 162 *@throws InterruptedException Description of the Exception 163 */ 164 public void join() throws InterruptedException { 165 threadImpl.join(); 166 } 167 168 /*** 169 * Description of the Method 170 * 171 *@throws InterruptedException Description of the Exception 172 */ 173 public void terminateAndWait() throws InterruptedException { 174 terminate(); 175 join(); 176 } 177 178 /*** 179 * 180 * @return 181 */ 182 public StopMode getStopMode() { 183 return stopMode; 184 } 185 186 /*** 187 * 188 * @param mode 189 */ 190 public void setStopMode(StopMode mode) { 191 stopMode = mode; 192 } 193 194 /*** 195 * 196 * @return 197 */ 198 public Priority getPriority() { 199 //return priority; 200 return Priority.parse(threadImpl.getPriority()); 201 } 202 203 /*** 204 * 205 * @param p 206 */ 207 public void setPriority(Priority p) { 208 priority = p; 209 210 if (!terminated) { 211 threadImpl.setPriority(p.num); 212 } 213 } 214 215 /*** 216 * 217 */ 218 protected void cleanup() throws InterruptedException { 219 } 220 221 /*** 222 * Description of the Method 223 */ 224 protected void beforeRun() throws InterruptedException { 225 } 226 227 /*** 228 * Description of the Method 229 */ 230 protected void afterRun() throws InterruptedException { 231 } 232 233 /*** 234 * Description of the Method 235 */ 236 protected void beforeExecute() throws InterruptedException { 237 } 238 239 /*** 240 * Description of the Method 241 */ 242 protected void afterExecute() throws InterruptedException { 243 } 244 245 /*** 246 * Adds a feature to the ThreadListener attribute of the IdThread object 247 * 248 *@param l The feature to be added to the ThreadListener attribute 249 */ 250 public void addThreadListener(IndyThreadListener l) { 251 synchronized (threadListeners) { 252 if (!threadListeners.contains(l)) { 253 threadListeners.add(l); 254 } 255 } 256 } 257 258 /*** 259 * 260 * @param l 261 */ 262 public void removeThreadListener(IndyThreadListener l) { 263 threadListeners.remove(l); 264 } 265 266 /*** 267 * 268 */ 269 private void doStopped() { 270 Collection l = null; 271 272 //don't want to block the list for the entire iteration (which could take any amount of time) 273 synchronized (threadListeners) { 274 l = Collections.unmodifiableCollection(threadListeners); 275 } 276 277 IndyThreadEvent evt = new IndyThreadEvent(this); 278 279 Iterator i = l.iterator(); 280 281 while (i.hasNext()) { 282 ((IndyThreadListener) i.next()).onStopped(evt); 283 } 284 } 285 286 /*** 287 * 288 */ 289 private void doException() { 290 Collection l = null; 291 292 //don't want to block the list for the entire iteration (which could take any amount of time) 293 synchronized (threadListeners) { 294 l = Collections.unmodifiableCollection(threadListeners); 295 } 296 297 IndyThreadEvent evt = new IndyThreadEvent(this); 298 299 Iterator i = l.iterator(); 300 301 while (i.hasNext()) { 302 ((IndyThreadListener) i.next()).onException(evt); 303 } 304 } 305 306 /*** 307 * An enumertaed class describing the possible stopping modes for an IndyThread. 308 * 309 * <code>TERMINATE</code> means that any call to stop will terminate the thread, and the IndyThread instance will be unuseable. 310 * <code>SUSPEND</code> means that the thread will pause and can be restarted. 311 * 312 * @author OTG 313 * @version 1.0 314 * @see IndyThread 315 */ 316 public static class StopMode { 317 /*** 318 * Used to signal that the enclosing <code>IndyThread</code> should terminate when stop is called. 319 * 320 * @see IndyThread#stop() 321 */ 322 public static final StopMode TERMINATE = new StopMode("Terminate"); 323 324 /*** 325 * Used to signal that the enclosing <code>IndyThread</code> should suspend when stop is called. 326 * 327 * @see IndyThread#stop() 328 */ 329 public static final StopMode SUSPEND = new StopMode("Suspend"); 330 331 /*** 332 * A string representation of this <code>StopMode</code> 333 */ 334 private final String friendlyName; 335 336 /*** 337 * Constructs a new <code>StopMode</code>; private to prevent inheritence. 338 * 339 * @param friendlyName The string representation of this <code>StopMode</code> 340 */ 341 private StopMode(String friendlyName) { 342 this.friendlyName = friendlyName; 343 } 344 345 /*** 346 * Returns a string representation of this <code>StopMode</code> as a friendly name. 347 * 348 * @return A user friendly string for this <code>StopMode</code> 349 */ 350 public String toString() { 351 return friendlyName; 352 } 353 } 354 355 /*** 356 * Represents IndyThread priority. 357 * 358 * 359 */ 360 public static class Priority { 361 /*** 362 * 363 */ 364 public static final Priority MIN = new Priority(Thread.MIN_PRIORITY); 365 366 /*** 367 * 368 */ 369 public static final Priority NORMAL = new Priority(Thread.NORM_PRIORITY); 370 371 /*** 372 * 373 */ 374 public static final Priority MAX = new Priority(Thread.MAX_PRIORITY); 375 376 /*** 377 * 378 */ 379 private final int num; 380 381 /*** 382 * 383 * @param num 384 */ 385 private Priority(int num) { 386 this.num = num; 387 } 388 389 public static Priority parse(int value) { 390 System.err.println(value); 391 392 switch (value) { 393 case 1: 394 case 2: 395 case 3: 396 return MIN; 397 398 case 4: 399 case 5: 400 case 6: 401 return NORMAL; 402 403 case 7: 404 case 8: 405 case 9: 406 case 10: 407 return MAX; 408 409 default: 410 throw new IllegalArgumentException( 411 "Not a valid thread priority value (1..10)"); 412 } 413 } 414 } 415 416 /*** 417 * 418 * <p>Title: </p> 419 * <p>Description: </p> 420 * <p>Copyright: Copyright (c) 2002</p> 421 * <p>Company: </p> 422 * @author unascribed 423 * @version 1.0 424 */ 425 private class IndyThreadImpl extends Thread { 426 public void run() { 427 try { 428 try { 429 beforeExecute(); 430 431 while (!terminated) { 432 if (stopped) { 433 doStopped(); 434 435 if (stopped) { 436 if (terminated) { 437 break; 438 } 439 440 IndyThread.this.suspend(); 441 442 if (terminated) { 443 break; 444 } 445 } 446 447 //if stopped inner 448 } 449 450 //if stopped outer 451 try { 452 beforeRun(); 453 454 try { 455 while (!stopped) { 456 IndyThread.this.run(); 457 } 458 } 459 finally { 460 afterRun(); 461 } 462 } 463 finally { 464 cleanup(); 465 } 466 } 467 468 //while !terminated 469 } 470 471 //tryf 472 finally { 473 afterExecute(); 474 } 475 } 476 477 //tryc 478 catch (Exception e) { 479 terminatingException = e; 480 doException(); 481 terminate(); 482 } 483 } 484 } 485 486 //inner class 487 }

This page was automatically generated by Maven