001: /*
002: * <copyright>
003: * Copyright 1997-2003 BBNT Solutions, LLC
004: * under sponsorship of the Defense Advanced Research Projects Agency (DARPA).
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the Cougaar Open Source License as published by
008: * DARPA on the Cougaar Open Source Website (www.cougaar.org).
009: *
010: * THE COUGAAR SOFTWARE AND ANY DERIVATIVE SUPPLIED BY LICENSOR IS
011: * PROVIDED 'AS IS' WITHOUT WARRANTIES OF ANY KIND, WHETHER EXPRESS OR
012: * IMPLIED, INCLUDING (BUT NOT LIMITED TO) ALL IMPLIED WARRANTIES OF
013: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND WITHOUT
014: * ANY WARRANTIES AS TO NON-INFRINGEMENT. IN NO EVENT SHALL COPYRIGHT
015: * HOLDER BE LIABLE FOR ANY DIRECT, SPECIAL, INDIRECT OR CONSEQUENTIAL
016: * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE OF DATA OR PROFITS,
017: * TORTIOUS CONDUCT, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
018: * PERFORMANCE OF THE COUGAAR SOFTWARE.
019: * </copyright>
020: */
021:
022: package org.cougaar.core.thread;
023:
024: import org.cougaar.util.log.Logger;
025: import org.cougaar.util.log.Logging;
026:
027: /**
028: * The simplest thread service implementation, which runs its {@link
029: * Schedulable}s serially, uses a small Collection of
030: * SerialThreadRunners to do that work. Each uses its own native Java
031: * Thread. The {@link Schedulable}s are held in order in a {@link
032: * SerialThreadQueue}.
033: */
034: final class SerialThreadRunner {
035: private Thread thread;
036:
037: private TrivialSchedulable current;
038:
039: private SerialThreadQueue queue;
040:
041: /** Boolean value used to notify the Body thread when
042: * the SerialThreadRunner is unloaded. */
043: private boolean isRunning;
044:
045: private Logger logger = Logging.getLogger(getClass().getName());
046:
047: SerialThreadRunner(SerialThreadQueue queue) {
048: this .queue = queue;
049: thread = new Thread(new Body(), "Serial Thread Runner");
050: thread.setDaemon(true);
051: isRunning = true;
052: thread.start();
053: }
054:
055: Thread getThread() {
056: return thread;
057: }
058:
059: int iterateOverThreads(ThreadStatusService.Body body) {
060: TrivialSchedulable sched = current;
061: if (sched != null) {
062: try {
063: body.run("root", sched);
064: } catch (Throwable t) {
065: logger.error("ThreadStatusService error in body", t);
066: return 0;
067: }
068: }
069: return 1;
070: }
071:
072: private void dequeue() {
073: while (true) {
074: synchronized (queue.getLock()) {
075: current = queue.next();
076: }
077: if (current == null)
078: return;
079:
080: current.setState(CougaarThread.THREAD_RUNNING);
081: current.getRunnable().run();
082: current.thread_stop(); // sets the state to DORMANT
083: current = null;
084: }
085: }
086:
087: private class Body implements Runnable {
088: public void run() {
089: Object lock = queue.getLock();
090: // Loop until the SerialThreadRunner is unloaded.
091: while (isRunning) {
092: dequeue();
093: synchronized (lock) {
094: while (queue.isEmpty()) {
095: try {
096: lock.wait();
097: break;
098: } catch (InterruptedException ex) {
099: }
100: }
101: }
102: }
103: }
104: }
105:
106: /**
107: * Gracefully shuts down this thread.
108: */
109: protected void stop() {
110: isRunning = false;
111: Object lock = queue.getLock();
112: synchronized (lock) {
113: lock.notify();
114: }
115: thread = null;
116: queue = null;
117: }
118:
119: }
|