001: /*
002: * $RCSfile: TimerThread.java,v $
003: *
004: * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
006: *
007: * This code is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License version 2 only, as
009: * published by the Free Software Foundation. Sun designates this
010: * particular file as subject to the "Classpath" exception as provided
011: * by Sun in the LICENSE file that accompanied this code.
012: *
013: * This code is distributed in the hope that it will be useful, but WITHOUT
014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: * version 2 for more details (a copy is included in the LICENSE file that
017: * accompanied this code).
018: *
019: * You should have received a copy of the GNU General Public License version
020: * 2 along with this work; if not, write to the Free Software Foundation,
021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
022: *
023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
024: * CA 95054 USA or visit www.sun.com if you need additional information or
025: * have any questions.
026: *
027: * $Revision: 1.8 $
028: * $Date: 2008/02/28 20:17:32 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: /**
035: * The TimerThread is thread that handle WakeupOnElapsedTime call.
036: * There is only one thread for the whole system.
037: */
038:
039: class TimerThread extends Thread {
040:
041: // action flag for runMonitor
042: private static final int WAIT = 0;
043: private static final int NOTIFY = 1;
044: private static final int STOP = 2;
045:
046: private WakeupOnElapsedTimeHeap heap = new WakeupOnElapsedTimeHeap();
047:
048: // Wakeup InputDeviceScheduler for every sample time reach
049: private WakeupOnElapsedTime inputDeviceSchedCond = new WakeupOnElapsedTime(
050: InputDeviceScheduler.samplingTime);
051:
052: // Wakeup {all?} Sound Scheduler{s} for every sample time reach
053: // QUESTION: this sampling time is set to a very large value so Sound
054: // Schedulers are not pinged often unless explicitly requested
055: // XXXX: need a way to remove/null this condition when all
056: // soundschedulers are halted
057: private WakeupOnElapsedTime soundSchedCond = new WakeupOnElapsedTime(
058: 120000); // every 2 minutes
059:
060: private volatile boolean running = true;
061: private boolean waiting = false;
062: private boolean ready = false;
063:
064: TimerThread(ThreadGroup t) {
065: super (t, "J3D-TimerThread");
066: }
067:
068: // call from UserThread
069: void add(WakeupOnElapsedTime wakeup) {
070: synchronized (heap) {
071: heap.insert(wakeup);
072: }
073: runMonitor(NOTIFY, 0);
074: }
075:
076: void addInputDeviceSchedCond() {
077: inputDeviceSchedCond.triggeredTime = InputDeviceScheduler.samplingTime
078: + J3dClock.currentTimeMillis();
079: add(inputDeviceSchedCond);
080: }
081:
082: void addSoundSchedCond(long wakeupTime) {
083: // XXXX: there are potentially multiple sound schedulers.
084: // this code will force a wait up on ALL sound schedulers
085: // even though only one needs to process the sound that
086: // this wakeup condition is triggered by.
087: soundSchedCond.triggeredTime = wakeupTime;
088: add(soundSchedCond);
089: }
090:
091: // call from MasterThread
092: void finish() {
093: runMonitor(STOP, 0);
094: }
095:
096: void remove(WakeupOnElapsedTime w) {
097: synchronized (heap) {
098: heap.extract(w);
099: }
100: }
101:
102: public void run() {
103: long waitTime = -1;
104: long time;
105: WakeupOnElapsedTime cond;
106:
107: while (running) {
108: runMonitor(WAIT, waitTime);
109: time = J3dClock.currentTimeMillis();
110:
111: while (true) {
112: cond = null;
113: waitTime = -1;
114: synchronized (heap) {
115: if (!heap.isEmpty()) {
116: waitTime = heap.getMin().triggeredTime - time;
117: if (waitTime <= 0) {
118: cond = heap.extractMin();
119: }
120: }
121: }
122: if (cond == null) {
123: break;
124: } else if (cond == inputDeviceSchedCond) {
125: VirtualUniverse.mc
126: .sendRunMessage(J3dThread.INPUT_DEVICE_SCHEDULER);
127: } else if (cond == soundSchedCond) {
128: VirtualUniverse.mc
129: .sendRunMessage(J3dThread.SOUND_SCHEDULER);
130: } else {
131: cond.setTriggered();
132: }
133: }
134: }
135: }
136:
137: synchronized void runMonitor(int action, long waitTime) {
138: switch (action) {
139: case WAIT:
140: // Issue 308 - wait unless ready flag already set
141: // Note that we can't loop since we need to be able to timeout
142: // after "waitTime" msec
143: if (running && !ready) {
144: waiting = true;
145: try {
146: if (waitTime < 0) {
147: wait();
148: } else {
149: wait(waitTime);
150: }
151: } catch (InterruptedException e) {
152: }
153: waiting = false;
154: }
155: ready = false;
156: break;
157: case NOTIFY:
158: ready = true;
159: if (waiting) {
160: notify();
161: }
162: break;
163: case STOP:
164: running = false;
165: notify();
166: break;
167: }
168: }
169:
170: }
|