001: /*
002: * $RCSfile: BehaviorScheduler.java,v $
003: *
004: * Copyright 1997-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.9 $
028: * $Date: 2008/02/28 20:17:19 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import java.util.ArrayList;
035: import java.util.logging.Level;
036:
037: class BehaviorScheduler extends J3dThread {
038:
039: /**
040: * The virtual universe that owns this BehaviorScheduler
041: */
042: VirtualUniverse univ = null;
043:
044: // reference to behaviourStructure processList
045: UnorderList processList[];
046:
047: // reference to scheduleList;
048: IndexedUnorderSet scheduleList;
049:
050: // reference to universe.behaviorStructure
051: BehaviorStructure behaviorStructure;
052:
053: // A count for BehaviorScheduler start/stop
054: int stopCount = -1;
055:
056: /**
057: * These are used for start/stop BehaviorScheduler
058: */
059: long lastStartTime;
060: long lastStopTime;
061:
062: // lock to ensure consistency of interval values read
063: Object intervalTimeLock = new Object();
064:
065: /**
066: * Some variables used to name threads correctly
067: */
068: private static int numInstances = 0;
069: private int instanceNum = -1;
070:
071: private synchronized int newInstanceNum() {
072: return (++numInstances);
073: }
074:
075: int getInstanceNum() {
076: if (instanceNum == -1)
077: instanceNum = newInstanceNum();
078: return instanceNum;
079: }
080:
081: BehaviorScheduler(ThreadGroup t, VirtualUniverse universe) {
082: super (t);
083: setName("J3D-BehaviorScheduler-" + getInstanceNum());
084: this .univ = universe;
085: behaviorStructure = universe.behaviorStructure;
086: scheduleList = behaviorStructure.scheduleList;
087: processList = behaviorStructure.processList;
088: type = J3dThread.BEHAVIOR_SCHEDULER;
089: }
090:
091: void stopBehaviorScheduler(long[] intervalTime) {
092:
093: stopCount = 2;
094: VirtualUniverse.mc.sendRunMessage(univ,
095: J3dThread.BEHAVIOR_SCHEDULER);
096: while (!userStop) {
097: MasterControl.threadYield();
098: }
099: synchronized (intervalTimeLock) {
100: intervalTime[0] = lastStartTime;
101: intervalTime[1] = lastStopTime;
102: }
103: }
104:
105: void startBehaviorScheduler() {
106: // don't allow scheduler start until intervalTime is read
107: synchronized (intervalTimeLock) {
108: stopCount = -1;
109: userStop = false;
110: VirtualUniverse.mc.setWork();
111: }
112: }
113:
114: void deactivate() {
115: active = false;
116: if (stopCount >= 0) {
117: userStop = true;
118: }
119: }
120:
121: /**
122: * The main loop for the Behavior Scheduler.
123: * Main method for firing off vector of satisfied conditions that
124: * are contained in the condMet vector. Method is synchronized
125: * because it is modifying the current wakeup vectors in the
126: * clean (emptying out satisfied conditions) and processStimulus
127: * (adding conditions again if wakeupOn called) calls.
128: */
129: void doWork(long referenceTime) {
130: BehaviorRetained arr[];
131: UnorderList list;
132: int i, size, interval;
133:
134: lastStartTime = J3dClock.currentTimeMillis();
135:
136: if (stopCount >= 0) {
137: VirtualUniverse.mc.sendRunMessage(univ,
138: J3dThread.BEHAVIOR_SCHEDULER);
139: if (--stopCount == 0) {
140: userStop = true;
141: }
142: }
143:
144: for (interval = 0; interval < BehaviorRetained.NUM_SCHEDULING_INTERVALS; interval++) {
145:
146: list = processList[interval];
147:
148: if (list.isEmpty()) {
149: continue;
150: }
151: arr = (BehaviorRetained[]) list.toArray(false);
152:
153: size = list.arraySize();
154:
155: for (i = 0; i < size; i++) {
156: BehaviorRetained behavret = arr[i];
157:
158: synchronized (behavret) {
159: Behavior behav = (Behavior) behavret.source;
160:
161: if (!behav.isLive() || !behavret.conditionSet
162: || (behavret.wakeupCondition == null)) {
163: continue;
164: }
165:
166: if (behavret.wakeupCondition.trigEnum == null) {
167: behavret.wakeupCondition.trigEnum = new WakeupCriteriaEnumerator(
168: behavret.wakeupCondition,
169: WakeupCondition.TRIGGERED_ELEMENTS);
170: } else {
171: behavret.wakeupCondition.trigEnum.reset(
172: behavret.wakeupCondition,
173: WakeupCondition.TRIGGERED_ELEMENTS);
174: }
175:
176: // BehaviorRetained now cache the old
177: // wakeupCondition in order to
178: // reuse it without the heavyweight cleanTree()
179: // behavret.wakeupCondition.cleanTree();
180:
181: behavret.conditionSet = false;
182: WakeupCondition wakeupCond = behavret.wakeupCondition;
183:
184: synchronized (behavret) {
185: behavret.inCallback = true;
186: univ.inBehavior = true;
187: try {
188: behav.processStimulus(wakeupCond.trigEnum);
189: } catch (RuntimeException e) {
190: // Force behavior condition to be unset
191: // Issue 21: don't call cleanTree here
192: behavret.conditionSet = false;
193: System.err
194: .println("Exception occurred during Behavior execution:");
195: e.printStackTrace();
196: } catch (Error e) {
197: // Force behavior condition to be unset
198: // Fix for issue 264
199: behavret.conditionSet = false;
200: System.err
201: .println("Error occurred during Behavior execution:");
202: e.printStackTrace();
203: }
204: univ.inBehavior = false;
205: behavret.inCallback = false;
206: }
207: // note that if the behavior wasn't reset, we need to make the
208: // wakeupcondition equal to null
209: if (behavret.conditionSet == false) {
210: if (wakeupCond != null) {
211: wakeupCond.cleanTree(behaviorStructure);
212: }
213: behavret.wakeupCondition = null;
214: behavret.active = false;
215: scheduleList.remove(behavret);
216: } else {
217: behavret.handleLastWakeupOn(wakeupCond,
218: behaviorStructure);
219: }
220: }
221: }
222: list.clear();
223: }
224:
225: behaviorStructure.handleAWTEvent();
226: behaviorStructure.handleBehaviorPost();
227: lastStopTime = J3dClock.currentTimeMillis();
228:
229: if (MasterControl.isStatsLoggable(Level.FINE)) {
230: VirtualUniverse.mc.recordTime(
231: MasterControl.TimeType.BEHAVIOR,
232: (lastStopTime - lastStartTime) * 1000000);
233: }
234: }
235:
236: void free() {
237: behaviorStructure = null;
238: getThreadData(null, null).thread = null;
239: univ = null;
240: for (int i = BehaviorRetained.NUM_SCHEDULING_INTERVALS - 1; i >= 0; i--) {
241: processList[i].clear();
242: }
243: scheduleList.clear();
244: }
245: }
|