package org.oscim.utils.async; import org.oscim.map.Map; /** * Simple 'Double Buffering' worker for running Tasks on AsyncExecutor * thread. */ public abstract class SimpleWorker<T> implements Runnable { protected final Map mMap; protected boolean mRunning; protected boolean mWait; protected boolean mCancel; protected boolean mDelayed; protected long mMinDelay; /** 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 SimpleWorker(Map map, long minDelay, T t1, T t2) { mMap = map; mMinDelay = minDelay; mTaskTodo = t1; mTaskLocked = t2; } @Override public void run() { synchronized (this) { if (mCancel) { mCancel = false; mRunning = false; mDelayed = false; mWait = false; if (mTaskTodo != null) cleanup(mTaskTodo); finish(); return; } // FIXME: mTaskTodo == null? if (mDelayed || mTaskTodo == null) { if (mDelayed && mTaskTodo != null) onMainLoop(mTaskTodo); // entered on main-loop mDelayed = false; // unset running temporarily mRunning = false; submit(0); return; } } boolean done = doWork(mTaskTodo); synchronized (this) { mRunning = false; if (mCancel) { cleanup(mTaskTodo); 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); mWait = false; } } } public abstract boolean doWork(T task); public abstract void cleanup(T task); public void finish() { } /** do stuff on main-loop before executing the task */ public void onMainLoop(T task) { } /** * If delay > 0 onMainLoop will be called before Task * is passed to worker-thread */ public synchronized void submit(long delay) { if (mRunning) { mWait = true; return; } mRunning = true; if (delay <= 0) { mMap.addTask(this); return; } if (!mDelayed) { mDelayed = true; mMap.postDelayed(this, delay); } } 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) { mCancel = true; return; } cleanup(mTaskTodo); finish(); } public synchronized boolean isRunning() { return mRunning; } }