implement managing of tasks instances in ContinuousTask
This commit is contained in:
parent
c8d79ee6fc
commit
401b0bf2dc
@ -68,6 +68,8 @@ public class LabelLayer extends Layer implements Map.InputListener, Map.UpdateLi
|
|||||||
public void onMapUpdate(MapPosition mapPosition, boolean changed, boolean clear) {
|
public void onMapUpdate(MapPosition mapPosition, boolean changed, boolean clear) {
|
||||||
if (clear)
|
if (clear)
|
||||||
mTextRenderer.clearLabels();
|
mTextRenderer.clearLabels();
|
||||||
|
|
||||||
|
mTextRenderer.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
// @Override
|
||||||
|
|||||||
@ -53,9 +53,11 @@ import org.oscim.utils.FastMath;
|
|||||||
import org.oscim.utils.OBB2D;
|
import org.oscim.utils.OBB2D;
|
||||||
import org.oscim.utils.async.ContinuousTask;
|
import org.oscim.utils.async.ContinuousTask;
|
||||||
import org.oscim.utils.pool.Pool;
|
import org.oscim.utils.pool.Pool;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
class TextRenderer extends ElementRenderer {
|
class TextRenderer extends ElementRenderer {
|
||||||
//static final Logger log = LoggerFactory.getLogger(TextRenderLayer.class);
|
static final Logger log = LoggerFactory.getLogger(TextRenderer.class);
|
||||||
|
|
||||||
private final static float MIN_CAPTION_DIST = 5;
|
private final static float MIN_CAPTION_DIST = 5;
|
||||||
private final static float MIN_WAY_DIST = 3;
|
private final static float MIN_WAY_DIST = 3;
|
||||||
@ -65,10 +67,10 @@ class TextRenderer extends ElementRenderer {
|
|||||||
private final Viewport mViewport;
|
private final Viewport mViewport;
|
||||||
private final TileSet mTileSet;
|
private final TileSet mTileSet;
|
||||||
|
|
||||||
class TextureLayers {
|
//private ElementLayers mDebugLayer;
|
||||||
boolean ready;
|
|
||||||
|
|
||||||
final TextureLayer l;
|
class TextureLayers {
|
||||||
|
final TextureLayer layers;
|
||||||
final TextLayer textLayer;
|
final TextLayer textLayer;
|
||||||
final SymbolLayer symbolLayer;
|
final SymbolLayer symbolLayer;
|
||||||
|
|
||||||
@ -80,17 +82,12 @@ class TextRenderer extends ElementRenderer {
|
|||||||
symbolLayer = new SymbolLayer();
|
symbolLayer = new SymbolLayer();
|
||||||
textLayer = new TextLayer();
|
textLayer = new TextLayer();
|
||||||
|
|
||||||
l = symbolLayer;
|
layers = symbolLayer;
|
||||||
l.next = textLayer;
|
symbolLayer.next = textLayer;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// used by GL thread
|
|
||||||
private TextureLayers mCurLayer;
|
|
||||||
|
|
||||||
// used by labeling thread
|
|
||||||
private TextureLayers mNextLayer;
|
|
||||||
|
|
||||||
// thread local pool (labeling)
|
// thread local pool (labeling)
|
||||||
class LabelPool extends Pool<TextItem> {
|
class LabelPool extends Pool<TextItem> {
|
||||||
Label releaseAndGetNext(Label l) {
|
Label releaseAndGetNext(Label l) {
|
||||||
@ -139,9 +136,6 @@ class TextRenderer extends ElementRenderer {
|
|||||||
layers.textureLayers = new TextLayer();
|
layers.textureLayers = new TextLayer();
|
||||||
layers.textureLayers.next = new SymbolLayer();
|
layers.textureLayers.next = new SymbolLayer();
|
||||||
|
|
||||||
mCurLayer = new TextureLayers();
|
|
||||||
mNextLayer = new TextureLayers();
|
|
||||||
|
|
||||||
//mActiveTiles = new HashMap<MapTile, LabelTile>();
|
//mActiveTiles = new HashMap<MapTile, LabelTile>();
|
||||||
mRelabelCnt = 0;
|
mRelabelCnt = 0;
|
||||||
|
|
||||||
@ -241,6 +235,15 @@ class TextRenderer extends ElementRenderer {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean iconIsVisible(int x, int y) {
|
||||||
|
// rough filter
|
||||||
|
float dist = x * x + y * y;
|
||||||
|
if (dist > mSquareRadius)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean wayIsVisible(TextItem ti) {
|
private boolean wayIsVisible(TextItem ti) {
|
||||||
// rough filter
|
// rough filter
|
||||||
float dist = ti.x * ti.x + ti.y * ti.y;
|
float dist = ti.x * ti.x + ti.y * ti.y;
|
||||||
@ -258,8 +261,6 @@ class TextRenderer extends ElementRenderer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ElementLayers mDebugLayer;
|
|
||||||
|
|
||||||
private Label getLabel() {
|
private Label getLabel() {
|
||||||
Label l = (Label) mPool.get();
|
Label l = (Label) mPool.get();
|
||||||
l.active = Integer.MAX_VALUE;
|
l.active = Integer.MAX_VALUE;
|
||||||
@ -379,10 +380,10 @@ class TextRenderer extends ElementRenderer {
|
|||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean updateLabels() {
|
boolean updateLabels(TextureLayers work) {
|
||||||
// nextLayer is not loaded yet
|
// nextLayer is not loaded yet
|
||||||
if (mNextLayer.ready)
|
//if (mNextLayer.ready)
|
||||||
return false;
|
// return false;
|
||||||
|
|
||||||
// get current tiles
|
// get current tiles
|
||||||
boolean changedTiles = mTileLayer.getVisibleTiles(mTileSet);
|
boolean changedTiles = mTileLayer.getVisibleTiles(mTileSet);
|
||||||
@ -393,7 +394,7 @@ class TextRenderer extends ElementRenderer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapPosition pos = mNextLayer.pos;
|
MapPosition pos = work.pos;
|
||||||
|
|
||||||
synchronized (mViewport) {
|
synchronized (mViewport) {
|
||||||
changedPos = mViewport.getMapPosition(pos);
|
changedPos = mViewport.getMapPosition(pos);
|
||||||
@ -428,7 +429,7 @@ class TextRenderer extends ElementRenderer {
|
|||||||
//if (dbg != null)
|
//if (dbg != null)
|
||||||
// Debug.addDebugLayers(dbg);
|
// Debug.addDebugLayers(dbg);
|
||||||
|
|
||||||
SymbolLayer sl = mNextLayer.symbolLayer;
|
SymbolLayer sl = work.symbolLayer;
|
||||||
sl.clearItems();
|
sl.clearItems();
|
||||||
|
|
||||||
mRelabelCnt++;
|
mRelabelCnt++;
|
||||||
@ -570,13 +571,17 @@ class TextRenderer extends ElementRenderer {
|
|||||||
if (ti.texRegion == null)
|
if (ti.texRegion == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
int x = (int) ((dx + ti.x) * scale);
|
||||||
|
int y = (int) ((dy + ti.y) * scale);
|
||||||
|
|
||||||
|
if (!iconIsVisible(x, y))
|
||||||
|
continue;
|
||||||
|
|
||||||
SymbolItem s = SymbolItem.pool.get();
|
SymbolItem s = SymbolItem.pool.get();
|
||||||
|
|
||||||
s.texRegion = ti.texRegion;
|
s.texRegion = ti.texRegion;
|
||||||
s.x = (float) ((dx + ti.x) * scale);
|
s.x = x;
|
||||||
s.y = (float) ((dy + ti.y) * scale);
|
s.y = y;
|
||||||
s.billboard = true;
|
s.billboard = true;
|
||||||
|
|
||||||
sl.addSymbol(s);
|
sl.addSymbol(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -585,18 +590,16 @@ class TextRenderer extends ElementRenderer {
|
|||||||
// temporary used Label
|
// temporary used Label
|
||||||
l = (Label) mPool.release(l);
|
l = (Label) mPool.release(l);
|
||||||
|
|
||||||
TextLayer tl = mNextLayer.textLayer;
|
|
||||||
|
|
||||||
tl.labels = mLabels;
|
|
||||||
// draw text to bitmaps and create vertices
|
// draw text to bitmaps and create vertices
|
||||||
tl.prepare();
|
work.textLayer.labels = mLabels;
|
||||||
tl.labels = null;
|
work.textLayer.prepare();
|
||||||
|
work.textLayer.labels = null;
|
||||||
|
|
||||||
// remove tile locks
|
// remove tile locks
|
||||||
mTileLayer.releaseTiles(mTileSet);
|
mTileLayer.releaseTiles(mTileSet);
|
||||||
|
|
||||||
mDebugLayer = dbg;
|
//mDebugLayer = dbg;
|
||||||
mNextLayer.ready = true;
|
//mNextLayer.ready = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -607,90 +610,87 @@ class TextRenderer extends ElementRenderer {
|
|||||||
public synchronized void update(MapPosition pos, boolean changed,
|
public synchronized void update(MapPosition pos, boolean changed,
|
||||||
Matrices matrices) {
|
Matrices matrices) {
|
||||||
|
|
||||||
if (mNextLayer.ready) {
|
TextureLayers t;
|
||||||
// exchange current with next layers
|
synchronized (mLabelTask) {
|
||||||
TextureLayers tmp = mCurLayer;
|
|
||||||
mCurLayer = mNextLayer;
|
t = mLabelTask.poll();
|
||||||
mNextLayer = tmp;
|
|
||||||
mNextLayer.ready = false;
|
if (t == null)
|
||||||
|
return;
|
||||||
|
|
||||||
// clear textures and text items from previous layer
|
|
||||||
layers.clear();
|
layers.clear();
|
||||||
|
|
||||||
if (mDebugLayer != null) {
|
|
||||||
layers.baseLayers = mDebugLayer.baseLayers;
|
|
||||||
mDebugLayer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set new TextLayer to be uploaded and rendered
|
|
||||||
layers.textureLayers = mCurLayer.l;
|
|
||||||
mMapPosition = mCurLayer.pos;
|
|
||||||
|
|
||||||
compile();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mLabelTask.submit((mLastRun + MAX_RELABEL_DELAY) - System.currentTimeMillis());
|
// set new TextLayer to be uploaded and rendered
|
||||||
|
layers.textureLayers = t.layers;
|
||||||
|
mMapPosition = t.pos;
|
||||||
|
compile();
|
||||||
|
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void render(MapPosition pos, Matrices m) {
|
public synchronized void render(MapPosition pos, Matrices m) {
|
||||||
GLState.test(false, false);
|
GLState.test(false, false);
|
||||||
|
|
||||||
|
layers.vbo.bind();
|
||||||
|
|
||||||
float scale = (float) (mMapPosition.scale / pos.scale);
|
float scale = (float) (mMapPosition.scale / pos.scale);
|
||||||
|
|
||||||
setMatrix(pos, m, true);
|
if (layers.baseLayers != null) {
|
||||||
|
setMatrix(pos, m, true);
|
||||||
|
|
||||||
synchronized (layers) {
|
for (RenderElement l = layers.baseLayers; l != null;) {
|
||||||
layers.vbo.bind();
|
if (l.type == RenderElement.POLYGON) {
|
||||||
if (layers.baseLayers != null) {
|
l = PolygonLayer.Renderer.draw(pos, l, m, true, 1, false);
|
||||||
for (RenderElement l = layers.baseLayers; l != null;) {
|
} else {
|
||||||
if (l.type == RenderElement.POLYGON) {
|
float div = (float) (mMapPosition.scale / (1 << pos.zoomLevel));
|
||||||
l = PolygonLayer.Renderer.draw(pos, l, m, true, 1, false);
|
l = LineLayer.Renderer.draw(layers, l, pos, m, div);
|
||||||
} else {
|
|
||||||
float div = scale * (float) (pos.scale / (1 << pos.zoomLevel));
|
|
||||||
l = LineLayer.Renderer.draw(layers, l, pos, m, div);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setMatrix(pos, m, false);
|
|
||||||
|
|
||||||
for (RenderElement l = layers.textureLayers; l != null;)
|
|
||||||
l = TextureLayer.Renderer.draw(l, scale, m);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setMatrix(pos, m, false);
|
||||||
|
|
||||||
|
for (RenderElement l = layers.textureLayers; l != null;)
|
||||||
|
l = TextureLayer.Renderer.draw(l, scale, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
final class LabelTask extends ContinuousTask {
|
final class LabelTask extends ContinuousTask<TextureLayers> {
|
||||||
|
|
||||||
public LabelTask(Map map) {
|
public LabelTask(Map map) {
|
||||||
super(map, 10);
|
super(map, 10, new TextureLayers(), new TextureLayers());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doWork() {
|
public boolean doWork(TextureLayers t) {
|
||||||
|
|
||||||
if (updateLabels())
|
if (updateLabels(t)) {
|
||||||
mMap.render();
|
mMap.render();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
mLastRun = System.currentTimeMillis();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cleanup() {
|
public void cleanup(TextureLayers t) {
|
||||||
clearLabelsInternal();
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish() {
|
||||||
|
mLabels = (Label) mPool.releaseAll(mLabels);
|
||||||
|
mTileSet.releaseTiles();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final LabelTask mLabelTask;
|
private final LabelTask mLabelTask;
|
||||||
|
|
||||||
/* private */long mLastRun;
|
public void clearLabels() {
|
||||||
|
mLabelTask.cancel(true);
|
||||||
/* private */void clearLabelsInternal() {
|
|
||||||
mLabels = (Label) mPool.releaseAll(mLabels);
|
|
||||||
mTileSet.releaseTiles();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearLabels() {
|
public void update() {
|
||||||
mLabelTask.cancel();
|
mLabelTask.submit(MAX_RELABEL_DELAY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,12 @@ package org.oscim.utils.async;
|
|||||||
|
|
||||||
import org.oscim.map.Map;
|
import org.oscim.map.Map;
|
||||||
|
|
||||||
public abstract class ContinuousTask implements Runnable {
|
/**
|
||||||
|
* Simple 'Double Buffering' worker for running Tasks on AsyncExecutor
|
||||||
|
* thread.
|
||||||
|
*/
|
||||||
|
public abstract class ContinuousTask<T> implements Runnable {
|
||||||
|
|
||||||
private final Map mMap;
|
private final Map mMap;
|
||||||
|
|
||||||
protected boolean mRunning;
|
protected boolean mRunning;
|
||||||
@ -12,30 +17,40 @@ public abstract class ContinuousTask implements Runnable {
|
|||||||
|
|
||||||
protected long mMinDelay;
|
protected long mMinDelay;
|
||||||
|
|
||||||
public ContinuousTask(Map map, long minDelay) {
|
/** Stuff which can be processed on the worker thread. */
|
||||||
|
protected T mTaskTodo;
|
||||||
|
|
||||||
|
/** Stuff that is done an ready for being fetched by poll(). */
|
||||||
|
protected T mTaskDone;
|
||||||
|
|
||||||
|
/** Stuff that is ready - will not be modified in the worker. */
|
||||||
|
protected T mTaskLocked;
|
||||||
|
|
||||||
|
public ContinuousTask(Map map, long minDelay, T t1, T t2) {
|
||||||
mMap = map;
|
mMap = map;
|
||||||
mMinDelay = minDelay;
|
mMinDelay = minDelay;
|
||||||
|
|
||||||
|
mTaskTodo = t1;
|
||||||
|
mTaskLocked = t2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
//System.out.println("run " + mRunning + " "
|
|
||||||
// + mCancel + " " + mDelayed + " " + mWait);
|
|
||||||
|
|
||||||
if (mCancel) {
|
if (mCancel) {
|
||||||
mCancel = false;
|
mCancel = false;
|
||||||
mRunning = false;
|
mRunning = false;
|
||||||
mDelayed = false;
|
mDelayed = false;
|
||||||
mWait = false;
|
mWait = false;
|
||||||
cleanup();
|
cleanup(mTaskTodo);
|
||||||
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mDelayed) {
|
|
||||||
|
if (mDelayed || mTaskTodo == null) {
|
||||||
// entered on main-loop
|
// entered on main-loop
|
||||||
mDelayed = false;
|
mDelayed = false;
|
||||||
mWait = false;
|
|
||||||
// unset running temporarily
|
// unset running temporarily
|
||||||
mRunning = false;
|
mRunning = false;
|
||||||
submit(0);
|
submit(0);
|
||||||
@ -43,32 +58,43 @@ public abstract class ContinuousTask implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doWork();
|
boolean done = doWork(mTaskTodo);
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
mRunning = false;
|
mRunning = false;
|
||||||
|
|
||||||
if (mCancel)
|
if (mCancel) {
|
||||||
cleanup();
|
cleanup(mTaskTodo);
|
||||||
else if (mWait)
|
finish();
|
||||||
|
mCancel = false;
|
||||||
|
} else if (done) {
|
||||||
|
mTaskDone = mTaskTodo;
|
||||||
|
mTaskTodo = null;
|
||||||
|
} else if (mWait) {
|
||||||
|
// only submit if not 'done'
|
||||||
|
// as otherwise there is no
|
||||||
|
// mStuffTodo
|
||||||
submit(mMinDelay);
|
submit(mMinDelay);
|
||||||
|
mWait = false;
|
||||||
mCancel = false;
|
}
|
||||||
mWait = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void doWork();
|
public abstract boolean doWork(T task);
|
||||||
|
|
||||||
public abstract void cleanup();
|
public abstract void cleanup(T task);
|
||||||
|
|
||||||
|
public void finish() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void submit(long delay) {
|
public synchronized void submit(long delay) {
|
||||||
//System.out.println("submit " + mRunning + " " + mCancel + " " + delay);
|
|
||||||
|
|
||||||
if (mRunning) {
|
if (mRunning) {
|
||||||
mWait = true;
|
mWait = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mRunning = true;
|
mRunning = true;
|
||||||
if (delay <= 0) {
|
if (delay <= 0) {
|
||||||
mMap.addTask(this);
|
mMap.addTask(this);
|
||||||
@ -80,12 +106,31 @@ public abstract class ContinuousTask implements Runnable {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void cancel() {
|
public synchronized T poll() {
|
||||||
|
if (mTaskDone == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
cleanup(mTaskLocked);
|
||||||
|
mTaskTodo = mTaskLocked;
|
||||||
|
|
||||||
|
mTaskLocked = mTaskDone;
|
||||||
|
mTaskDone = null;
|
||||||
|
|
||||||
|
if (mWait) {
|
||||||
|
submit(mMinDelay);
|
||||||
|
mWait = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mTaskLocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void cancel(boolean clear) {
|
||||||
if (mRunning) {
|
if (mRunning) {
|
||||||
mCancel = true;
|
mCancel = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup();
|
cleanup(mTaskTodo);
|
||||||
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user