return this.stopRequested;
}
private class SchedulerThread implements Runnable {
/* Gets the next task whenever the last one finishes */
@SuppressWarnings("unchecked")
public void run() {
try {
synchronized (MeasurementScheduler.this) {
checkinFuture =
checkinExecutor.scheduleAtFixedRate(checkinTask, 0L, checkinIntervalSec,
TimeUnit.SECONDS);
}
/* Loop invariant: pendingTasks always contains the scheduled tasks
* and taskQueue contains new tasks that have not been scheduled
*/
while (!isStopRequested()) {
Log.i(SpeedometerApp.TAG, "Checking queue for new tasks");
if (isPauseRequested()) {
synchronized (MeasurementScheduler.this) {
try {
Log.i(SpeedometerApp.TAG, "User requested pause");
MeasurementScheduler.this.wait();
} catch (InterruptedException e) {
Log.e(SpeedometerApp.TAG, "scheduler pause is interrupted");
}
}
}
/* Schedule the new tasks and move them from taskQueu to pendingTasks
*
* TODO(Wenjie): We may also need a separate rule (taskStack) for user
* generated tasks because users may prefer to run the latest scheduled
* task first, which is LIFO and is different from the FIFO semantics in
* the priority queue.
*/
MeasurementTask task;
try {
while ((task = taskQueue.take()) != null) {
Log.i(SpeedometerApp.TAG, "New task arrived. There are " + taskQueue.size()
+ " tasks in taskQueue");
ScheduledFuture future = null;
if (!task.isPassedDeadline()) {
future = executor.schedule(task, task.timeFromExecution(), TimeUnit.SECONDS);
if (task.measurementDesc.endTime != null) {
long delay = task.measurementDesc.endTime.getTime() - System.currentTimeMillis();
CancelTask cancelTask = new CancelTask(future);
cancelExecutor.schedule(cancelTask, delay, TimeUnit.MILLISECONDS);
}
Log.i(SpeedometerApp.TAG,
"task " + task + " will start in " + task.timeFromExecution() / 1000
+ " seconds");
}
synchronized (pendingTasks) {
pendingTasks.put(task, future);
}
Log.i(SpeedometerApp.TAG, "There are " + pendingTasks.size() + " in pendingTasks");
}
} catch (InterruptedException e) {
Log.e(SpeedometerApp.TAG, "interrupted while waiting for new tasks");
}
}
} finally {
/*
* either stop requested or unchecked exceptions occur. perform cleanup
*
* TODO(Wenjie): If this is not a user requested stop, we should thrown
* a exception to notify Speedometer so that it can restart the
* scheduler thread.
*/
cleanUp();
}
}
}
private MeasurementResult getFailureResult(MeasurementTask task) {
return new MeasurementResult(RuntimeUtil.getDeviceInfo().deviceId,
RuntimeUtil.getDeviceProperty(), task.getType(), Calendar.getInstance().getTime(),
false, task.measurementDesc);
}
} |