📄 wfcachemanager.java
字号:
package org.trinet.jiggle;
import java.util.*;
import javax.swing.*;
/**
* Manage the caching of waveforms. Allows only a fixed
* number of cached objects (waveforms) to exist in memory. <p>
*
* Because the Cache Manager really manages the WFViewList it should only be
* started after the WFViewList is created. */
public class WFCacheManager {
WFViewList wfvList;
// use Dimension here ??
int headroom = 100;
int footroom = 100;
int oldIndex = -1;
CacheMgrThread cacheMgrThread = null;
/** Flag to signal current CacheMgr thread to stop. */
boolean stopCacheMgr = false;
//boolean debug = true;
boolean debug = false;
public WFCacheManager (WFViewList list) {
if (debug) System.out.println("Starting WFCacheManager.");
setWFViewList(list);
}
public WFCacheManager (WFViewList list, int above, int below) {
this(list);
setCacheSize(above, below);
}
public WFCacheManager (WFViewList list, int above, int below, int index) {
this(list);
setCacheSize(above, below);
setIndex(index);
}
public void setWFViewList (WFViewList list) {
this.wfvList = list;
}
/** Specify the size of the cache by setting the number of panels above and below
* the index. The current index is considered part of the below value so that
* the Cache size = above + below. */
public void setCacheSize(int above, int below) {
headroom = above;
footroom = below;
if (debug) System.out.println ("setCacheSize: "+headroom +" / "+footroom);
//adjust to new size, leave index alone.
int idx = 0;
if (cacheMgrThread != null) idx = cacheMgrThread.cacheIndex;
restartCacheMgr(idx);
}
/** Returns true if the index is withing the range of the WFViewList. */
public boolean isLegalIndex(int index) {
return (index > -1 && index < (wfvList.size()-1));
}
public int getCacheSize () {
return headroom + footroom;
}
/** Move the logical index of the waveform cache to the new position. This stops
any previous CacheMgr thread and starts a new one to do the work in
background. Returns true if is was sucessful. */
public boolean setIndex (int index) {
if (index == oldIndex) return true; // no change
if (isLegalIndex(index)) {
if (debug) System.out.println ("WFCacheMgr: setIndex: "+index);
restartCacheMgr(index);
oldIndex = index;
return true;
} else {
return false;
}
}
/** This stops any previous CacheMgr thread and starts a new one to do the work
in background. */
public void restartCacheMgr (int index) {
if (debug) System.out.println ("WFCacheMgr: restart");
stopCacheMgr();
cacheMgrThread = new CacheMgrThread(wfvList, index);
}
/** Stop the waveforms loader thread. Thread will stop after next waveform
load is done. Caller will block until old CacheMgr thread stops. */
public void stopCacheMgr() {
if (debug) System.out.println ("WFCacheMgr: stop");
if (cacheMgrThread != null &&
cacheMgrThread.thread != null) {
cacheMgrThread.setStopFlag(true); // kill predicessor
while (cacheMgrThread.thread.isAlive()) { // wait for shutdown
try {
Thread.sleep(10);
} catch (InterruptedException e){}
}
cacheMgrThread = null;
}
}
public String toString() {
return "WFCacheManager: "+
" headroom = "+ headroom +" "+
" footroom = "+ footroom +" "+
" wfvList-size = " + wfvList.size();
}
//////// INNER CLASS
class CacheMgrThread implements Runnable {
WFViewList wfvList;
public Thread thread;
boolean stopFlag = false;
int cacheIndex;
int top, bottom;
// constructor - also starts thread
public CacheMgrThread (WFViewList wfvList, int index) {
cacheIndex = index;
this.wfvList = wfvList;
if (wfvList.size() == 0) return; // short circuit on blank list
String threadName = "CacheMgr"+cacheIndex;
thread = new Thread(this, threadName);
stopFlag = false;
if (debug) System.out.println("Creating CacheMgrThread "+ threadName);
thread.start();
}
public synchronized void setStopFlag(boolean tf) {
stopFlag = tf;
}
public synchronized boolean getStopFlag() {
return stopFlag;
}
// real work is done here
public void run () {
// set thread priority to 1/2 normal
thread.setPriority(Thread.NORM_PRIORITY/2);
int i; // instantiate increment only once (more efficient?)
if (debug) System.out.println ("cacheMgr run: wfvList length = "+wfvList.size());
WFView wfv[] = wfvList.getArray();
// recalc the cache bounds
int cacheSize = headroom + footroom;
int lastIdx = wfv.length - 1;
if (cacheSize > wfv.length) { // cache is bigger then data
top = 0;
bottom = lastIdx;
} else {
top = cacheIndex - headroom;
bottom = top + cacheSize;
if (top < 0) {
top = 0;
bottom = cacheSize;
}
if (bottom > lastIdx) {
top = lastIdx - cacheSize;
bottom = lastIdx;
}
}
if (debug) System.out.println ("I'm a new cacheMgr thread! "+
"headroom= " + headroom + " "+
"footroom= " + footroom + " "+
"top= "+ top + " "+
"bottom= "+ bottom + " " +
"cacheIndex= " + cacheIndex + " "+
"wfv.length= "+ wfv.length);
// release space for stuff now outside the cache bounds
// above
for (i = 0; i < top; i++) {
unloadwf(wfv[i]);
//new WfUnloader(wfv[i]);
}
if (getStopFlag()) return;
// below
for (i = bottom+1; i < wfv.length ; i++) {
unloadwf(wfv[i]);
//new WfUnloader(wfv[i]);
}
if (getStopFlag()) return;
// load new data from pointer down, this insures that the Waveforms in view
// are loaded first.
/* wfv[i].loadTimeSeries() does not reload if its already loaded.
NOTE: if time-series is unavailable for some reason, loading will be
attempted each time thru this loop. This could cause slow cache
performance if it takes a long time for a data read to fail. */
for (i = cacheIndex; i <= bottom; i++) {
loadwf(wfv[i]);
//new WfLoader(wfv[i]);
thread.yield(); // allow other threads to execute
if (getStopFlag()) return;
}
// load from pointer up
for (i = cacheIndex - 1; i >= top; i--) {
loadwf(wfv[i]);
//new WfLoader(wfv[i]);
thread.yield(); // allow other threads to execute
if (getStopFlag()) return;
}
} // end of run()
protected boolean loadwf(WFView wfv) {
if (debug) System.out.println ("CacheMgr loaded= "+
wfv.getChannelObj().toDelimitedSeedString());
return wfv.loadTimeSeries();
}
protected boolean unloadwf(WFView wfv) {
if (debug) System.out.println ("CacheMgr unloaded= "+
wfv.getChannelObj().toDelimitedSeedString());
return wfv.unloadTimeSeries();
}
// Did the following in an attempt to track dow a VM crash
// Thought maybe the load/unload of a wf fired an event that was being
// executed in this thread and causing conflicts.
// Turns out that wf inherits its fireevent() method form JasiObject
// that already call Swing.invokeLater(), so this was a waste of time
// and didn't fix the VM crash.
/*
class WfUnloader implements Runnable {
WFView wfv;
protected WfUnloader (WFView wfv) {
this.wfv = wfv;
SwingUtilities.invokeLater(this);
}
public void run() {
wfv.unloadTimeSeries();
if (debug) System.out.println ("Cache unloaded= "+
wfv.getChannelObj().toDelimitedSeedString());
}
}
class WfLoader implements Runnable {
WFView wfv;
protected WfLoader (WFView wfv) {
this.wfv = wfv;
SwingUtilities.invokeLater(this);
}
public void run() {
wfv.loadTimeSeries();
if (debug) System.out.println ("Cache loaded= "+
wfv.getChannelObj().toDelimitedSeedString());
}
}
*/
} // end of inner class
} // WFCacheMgr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -