package org.pyload.android.client.module; import java.util.HashMap; import java.util.LinkedList; import java.util.Map.Entry; import org.pyload.android.client.pyLoadApp; import android.os.Handler; import android.util.Log; /** * Task Queue to ensure single threadedness but provide async taks, to avoid * blocking the GUI Thread Will catch all exceptions and post them to the * handler if found in exception map. * * @author RaNaN * */ public class TaskQueue { private final LinkedList<GuiTask> tasks = new LinkedList<GuiTask>(); private HashMap<Throwable, Runnable> exceptionMap; private Handler mHandler; private pyLoadApp app; private boolean running; private Runnable internalRunnable; private class InternalRunnable implements Runnable { public void run() { internalRun(); } } public TaskQueue(pyLoadApp app, Handler mHandler, HashMap<Throwable, Runnable> exceptionMap) { this.app = app; this.mHandler = mHandler; this.exceptionMap = exceptionMap; internalRunnable = new InternalRunnable(); } public void start() { if (!running) { Thread thread = new Thread(internalRunnable); thread.setDaemon(true); running = true; thread.start(); } } public void stop() { running = false; } public void clear() { tasks.clear(); } public void addTask(GuiTask task) { synchronized (tasks) { tasks.addFirst(task); tasks.notify(); // notify any waiting threads } } private GuiTask getNextTask() { synchronized (tasks) { while (tasks.isEmpty()) { try { tasks.wait(); } catch (InterruptedException e) { Log.e("pyLoad", "Task interrupted", e); stop(); } } return tasks.removeLast(); } } private void internalRun() { while (running) { GuiTask task = getNextTask(); // TODO: unusable atm if (task.tries <= 0){ Log.d("pyLoad", task.toString()+ " has reached retry limit"); continue; } try { task.getTask().run(); mHandler.post(task.getSuccess()); } catch (Throwable t) { Log.e("pyLoad", "Task threw an exception", t); app.setLastException(t); if (task.hasCritical()){ mHandler.post(task.getCritical()); } if (task.hasExceptionMap()) { for (Entry<Throwable, Runnable> set : task .getExceptionMap().entrySet()) { if (t.getClass() == set.getKey().getClass()) { mHandler.post(set.getValue()); } } } for (Entry<Throwable, Runnable> set : exceptionMap.entrySet()) { if (t.getClass() == set.getKey().getClass()) { mHandler.post(set.getValue()); } } } } } }