📄 mastercontrol.java
字号:
return views.contains(view); } /** * This snapshots the time values to be used for this iteration. * Note that this method is called without the timeLock held. * We must synchronize on timeLock to prevent updating * thread.lastUpdateTime from user thread in sendMessage() * or sendRunMessage(). */ private void updateTimeValues() { synchronized (timeLock) { int i=0; J3dThreadData lastThread=null; J3dThreadData thread=null; long lastTime = currentTime; currentTime = getTime(); J3dThreadData threads[] = (J3dThreadData []) stateWorkThreads.toArray(false); int size = stateWorkThreads.arraySize(); while (i<lastTransformStructureThread) { thread = threads[i++]; if ((thread.lastUpdateTime > thread.lastRunTime) && !thread.thread.userStop) { lastThread = thread; thread.needsRun = true; thread.threadOpts = J3dThreadData.CONT_THREAD; thread.lastRunTime = currentTime; } else { thread.needsRun = false; } } if (lastThread != null) { lastThread.threadOpts = J3dThreadData.WAIT_ALL_THREADS; lastThread = null; } while (i<lastStructureUpdateThread) { thread = threads[i++]; if ((thread.lastUpdateTime > thread.lastRunTime) && !thread.thread.userStop) { lastThread = thread; thread.needsRun = true; thread.threadOpts = J3dThreadData.CONT_THREAD; thread.lastRunTime = currentTime; } else { thread.needsRun = false; } } if (lastThread != null) { lastThread.threadOpts = J3dThreadData.WAIT_ALL_THREADS; lastThread = null; } while (i<size) { thread = threads[i++]; if ((thread.lastUpdateTime > thread.lastRunTime) && !thread.thread.userStop) { lastThread = thread; thread.needsRun = true; thread.threadOpts = J3dThreadData.CONT_THREAD; thread.lastRunTime = currentTime; } else { thread.needsRun = false; } } if (lastThread != null) { lastThread.threadOpts = J3dThreadData.WAIT_ALL_THREADS; lastThread = null; } threads = (J3dThreadData []) renderWorkThreads.toArray(false); size = renderWorkThreads.arraySize(); View v; J3dThreadData lastRunThread = null; waitTimestamp++; sleepTime = 0L; boolean threadToRun = false; // Not currently used // Fix for Issue 12: loop through the list of threads, calling // computeCycleTime() exactly once per view. This ensures that // all threads for a given view see consistent values for // isMinCycleTimeAchieve and sleepTime. v = null; for (i=0; i<size; i++) { thread = threads[i]; if (thread.view != v) { thread.view.computeCycleTime(); // Set sleepTime to the value needed to satify the // minimum cycle time of the slowest view if (thread.view.sleepTime > sleepTime) { sleepTime = thread.view.sleepTime; } } v = thread.view; } v = null; for (i=0; i<size; i++) { thread = threads[i]; if (thread.canvas == null) { // Only for swap thread ((Object []) thread.threadArgs)[3] = null; } if ((thread.lastUpdateTime > thread.lastRunTime) && !thread.thread.userStop) { if (thread.thread.lastWaitTimestamp == waitTimestamp) { // This renderer thread is repeated. We must wait // until all previous renderer threads done before // allowing this thread to continue. Note that // lastRunThread can't be null in this case. waitTimestamp++; if (thread.view != v) { // A new View is start v = thread.view; threadToRun = true; lastRunThread.threadOpts = (J3dThreadData.STOP_TIMER | J3dThreadData.WAIT_ALL_THREADS); ((Object []) lastRunThread.threadArgs)[3] = lastRunThread.view; thread.threadOpts = (J3dThreadData.START_TIMER | J3dThreadData.CONT_THREAD); } else { if ((lastRunThread.threadOpts & J3dThreadData.START_TIMER) != 0) { lastRunThread.threadOpts = (J3dThreadData.START_TIMER | J3dThreadData.WAIT_ALL_THREADS); } else { lastRunThread.threadOpts = J3dThreadData.WAIT_ALL_THREADS; } thread.threadOpts = J3dThreadData.CONT_THREAD; } } else { if (thread.view != v) { v = thread.view; threadToRun = true; // Although the renderer thread is not // repeated. We still need to wait all // previous renderer threads if new View // start. if (lastRunThread != null) { lastRunThread.threadOpts = (J3dThreadData.STOP_TIMER | J3dThreadData.WAIT_ALL_THREADS); ((Object []) lastRunThread.threadArgs)[3] = lastRunThread.view; } thread.threadOpts = (J3dThreadData.START_TIMER | J3dThreadData.CONT_THREAD); } else { thread.threadOpts = J3dThreadData.CONT_THREAD; } } thread.thread.lastWaitTimestamp = waitTimestamp; thread.needsRun = true; thread.lastRunTime = currentTime; lastRunThread = thread; } else { thread.needsRun = false; } } if (lastRunThread != null) { lastRunThread.threadOpts = (J3dThreadData.STOP_TIMER | J3dThreadData.WAIT_ALL_THREADS| J3dThreadData.LAST_STOP_TIMER); lockGeometry = true; ((Object []) lastRunThread.threadArgs)[3] = lastRunThread.view; } else { lockGeometry = false; } } // Issue 275 - go to sleep without holding timeLock // Sleep for the amount of time needed to satisfy the minimum // cycle time for all views. if (sleepTime > 0) { // System.err.println("MasterControl: sleep(" + sleepTime + ")"); try { Thread.sleep(sleepTime); } catch (InterruptedException e) { System.err.println(e); } // System.err.println("MasterControl: done sleeping"); } } private void createUpdateThread(J3dStructure structure) { final J3dStructure s = structure; if (s.updateThread == null) { java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { synchronized (rootThreadGroup) { s.updateThread = new StructureUpdateThread( rootThreadGroup, s, s.threadType); s.updateThread.setPriority(threadPriority); } return null; } }); s.updateThread.initialize(); s.threadData.thread = s.updateThread; // This takes into accout for thread that just destroy and // create again. In this case the threadData may receive // message before the thread actually created. We don't want // the currentTime to overwrite the update time of which // is set by threadData when get message. s.threadData.lastUpdateTime = Math.max(currentTime, s.threadData.lastUpdateTime); } } private void emptyMessageList(J3dStructure structure, View v) { if (structure != null) { if (v == null) { if (structure.threadData != null) { structure.threadData.thread = null; } if (structure.updateThread != null) { structure.updateThread.structure = null; } structure.updateThread = null; } boolean otherViewExist = false; if ((v != null) && (v.universe != null)) { // Check if there is any other View register with the // same universe for (int i=views.size()-1; i >= 0; i--) { if (((View) views.get(i)).universe == v.universe) { otherViewExist = true; break; } } } UnorderList mlist = structure.messageList; // Note that message is add at the end of array synchronized (mlist) { int size = mlist.size(); if (size > 0) { J3dMessage mess[] = (J3dMessage []) mlist.toArray(false); J3dMessage m; int i = 0; Object oldRef= null; while (i < size) { m = mess[i]; if ((v == null) || (m.view == v) || ((m.view == null) && !otherViewExist)) { if (m.type == J3dMessage.INSERT_NODES) { // There is another View register request // immediately following, so no need // to remove message. break; } // Some other thread may still using this // message so we should not directly // add this message to free lists m.decRefcount(); mlist.removeOrdered(i); size--; } else { i++; } } } } } } private void destroyUpdateThread(J3dStructure structure) { // If unregisterView message got before EMPTY_UNIVERSE // message, then updateThread is already set to null. if (structure.updateThread != null) { structure.updateThread.finish(); structure.updateThread.structure = null; structure.updateThread = null; } structure.threadData.thread = null; structure.clearMessages(); } /** * This register a View with MasterControl. * The View has at least one Canvas3D added to a container. */ private void registerView(View v) { final VirtualUniverse univ = v.universe; if (views.contains(v) && regUniverseList.contains(univ)) { return; // already register } if (timerThread == null) { // This handle the case when MC shutdown and restart in // a series of pending request running = true; createMCThreads(); } // If viewId is null, assign one .. v.assignViewId(); // Create thread if not done before createUpdateThread(univ.behaviorStructure); createUpdateThread(univ.geometryStructure); createUpdateThread(univ.soundStructure); createUpdateThread(univ.renderingEnvironmentStructure); createUpdateThread(univ.transformStructure); // create Behavior scheduler J3dThreadData threadData = null; if (univ.behaviorScheduler == null) { java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Object run() { synchronized (rootThreadGroup) { univ.behaviorScheduler = new BehaviorScheduler( rootThreadGroup, univ); univ.behaviorScheduler.setPriority(threadPriority); } return null; } }); univ.behaviorScheduler.initialize(); univ.behaviorScheduler.userStop = v.stopBehavior; threadData = univ.behaviorScheduler.getThreadData(null, null); threadData.thread = univ.behaviorScheduler; threadData.threadType = J3dThread.BEHAVIOR_SCHEDULER; threadData.lastUpdateTime = Math.max(currentTime, threadData.lastUpdateTime); } createUpdateThread(v.renderBin); createUpdateThread(v.soundScheduler); if (v.physicalEnvironment != null) { v.physicalEnvironment.addUser(v); } // create InputDeviceScheduler evaluatePhysicalEnv(v); regUniverseList.addUnique(univ); views.addUnique(v); } /** * This unregister a View with MasterControl. * The View no longer has any Canvas3Ds in a container. */ private void unregisterView(View v) { if (!views.remove(v)) { v.active = false; v.doneUnregister = true; return; // already unregister } if (v.active) { viewDeactivate(v); } if(J3dDebug.devPhase) { J3dDebug.doDebug(J3dDebug.masterControl, J3dDebug.LEVEL_1, "MC: Destroy Sound Scheduler and RenderBin Update thread"); } v.soundScheduler.updateThread.finish(); v.renderBin.updateThread.finish(); v.soundScheduler.updateThread = null; v.renderBin.updateThread = null; // remove VirtualUniverse related threads if Universe // is empty VirtualUniverse univ = v.universe; int i; synchronized (timeLock) { // The reason we need to sync. with timeLock is because we // don't want user thread running sendMessage() to // dispatch it in different structure queue when // part of the structure list is empty at the same time. // This will cause inconsistence in the message reference // count. emptyMessageList(v.soundScheduler, v); emptyMessageList(v.renderBin, v); if (univ.isEmpty())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -