r2843 - branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks
Author: echatellier Date: 2012-03-27 12:47:23 +0200 (Tue, 27 Mar 2012) New Revision: 2843 Url: http://chorem.org/repositories/revision/jtimer/2843 Log: Add new algorithm based on atomic long Modified: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java Modified: branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java =================================================================== --- branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java 2012-03-27 09:35:07 UTC (rev 2842) +++ branches/1.4.0-ttalgo/src/main/java/org/chorem/jtimer/ui/tasks/RunTaskJob.java 2012-03-27 10:47:23 UTC (rev 2843) @@ -29,7 +29,7 @@ import java.util.Collection; import java.util.Date; import java.util.HashSet; -import java.util.List; +import java.util.concurrent.atomic.AtomicLong; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; @@ -41,9 +41,9 @@ import org.chorem.jtimer.JTimer; import org.chorem.jtimer.data.TimerDataManager; import org.chorem.jtimer.entities.TimerAlert; +import org.chorem.jtimer.entities.TimerAlert.Type; import org.chorem.jtimer.entities.TimerTask; import org.chorem.jtimer.entities.TimerTaskHelper; -import org.chorem.jtimer.entities.TimerAlert.Type; import org.chorem.jtimer.ui.system.SystemInfo; import org.chorem.jtimer.ui.system.SystemInfoFactory; import org.chorem.jtimer.ui.system.UnsupportedSystemInfoException; @@ -80,21 +80,9 @@ /** Already thrown alert. */ protected Collection<TimerAlert> alreadyTrownAlerts; - /** Timestamp when timing start. */ - protected long taskStartTimestamp; - /** Last publish time to detect hibernate. */ - protected long lastUserActivity; + protected AtomicLong lastUserActivity; - /** - * Offset to adjust time for current day (last activity day). - * Include : - * - Task initial time - * - Task idle time (task was running but time not counted) - * - Manual user incremented time - */ - protected long offsetTimeInMs; - /** Want to stop flag. */ protected Boolean bWantToStop; @@ -175,37 +163,6 @@ return managedTask; } - /** - * Method to increment time while task is running (in ms). - * - * @param increment increment, can be negative - */ - public void incrementTaskTime(long increment) { - - long nowTimestamp = Calendar.getInstance().getTimeInMillis(); - - // new var, to not modify parameter - long localIncrement = increment; - - // do go over 0 - if (nowTimestamp - taskStartTimestamp + offsetTimeInMs + increment < 0) { - localIncrement = -(nowTimestamp - taskStartTimestamp + offsetTimeInMs); - } - - offsetTimeInMs += localIncrement; - } - - /** - * Reset timing. - * - * For example if task goes over 0h00, need to reset... - */ - public void resetTiming() { - taskStartTimestamp = System.currentTimeMillis(); - lastUserActivity = taskStartTimestamp; - offsetTimeInMs = managedTask.getTime(new Date()) * 1000; - } - /* * @see org.jdesktop.swingworker.SwingWorker#doInBackground() */ @@ -216,8 +173,8 @@ // notify ui parentApp.startedTask(managedTask); - // init timing - resetTiming(); + // init + lastUserActivity = new AtomicLong(System.currentTimeMillis()); // get idle time long configIdleTime = JTimer.config.getIdleTime() * 1000; @@ -226,7 +183,9 @@ boolean dontWantToStop = true; while (dontWantToStop) { - long currentTime = System.currentTimeMillis(); + // this algorithm is based on this atomic operation + // that ensure hibernate won't break time tracking + long oldUserActivity = lastUserActivity.getAndSet(System.currentTimeMillis()); // check user idle time if (systemInfo != null) { // idle time available @@ -237,76 +196,35 @@ } } - // if long idleTime is unavailable, if is always false - if (idleTime >= configIdleTime) { - lastUserActivity -= idleTime; - } - // check for idleness with last user activity (real idle and hibernate) - if (currentTime - lastUserActivity >= configIdleTime) { + long delta = lastUserActivity.get() - oldUserActivity; + if (delta + idleTime >= configIdleTime) { - // update idle to publish time without counting idle - offsetTimeInMs -= currentTime - lastUserActivity; - publish(); + // remove delta from now + addTaskDelta(lastUserActivity.get(), -(delta + idleTime)); // display idle detected (blocking call) JTimer parentApplication = (JTimer) getApplication(); parentApplication.preIdleDetect(); - int option = IdleDialog.showIdleDialog(currentTime - idleTime); + int option = IdleDialog.showIdleDialog(delta); parentApplication.postIdleDetect(); - // manage tracking resume after idle - currentTime = System.currentTimeMillis(); - lastUserActivity = currentTime; - switch (option) { case IdleDialog.REVERT: // just stop the task ((JTimer) getApplication()).stopTask(managedTask); break; - + case IdleDialog.CONTINUE: - // refresh time - // remove idle time previously added - //offsetTimeInMs += idleTimeOffset; - //publish(taskTimingBeforeStartInMs + afterIdleTime - // - taskStartCalendar.getTimeInMillis() - // + offsetTimeInMs); - + // readd delta since oldUserActivity + addTaskDelta(oldUserActivity, delta + idleTime); break; - - case IdleDialog.RESUME: - // resume = increment idle time - offsetTimeInMs += currentTime - lastUserActivity; - // check day change (after offset) - Calendar nowCalendar = Calendar.getInstance(); - Calendar startCalendar = Calendar.getInstance(); - startCalendar.setTimeInMillis(taskStartTimestamp); - if (!DateUtils.isSameDay(startCalendar, nowCalendar)) { - resetTiming(); - } - - // update time - publish(); - break; } } else { - - // no idle detected - lastUserActivity = currentTime; - - // check day change - Calendar nowCalendar = Calendar.getInstance(); - Calendar startCalendar = Calendar.getInstance(); - startCalendar.setTimeInMillis(taskStartTimestamp); - if (!DateUtils.isSameDay(startCalendar, nowCalendar)) { - resetTiming(); - } - // update new time - publish(); + addTaskDelta(oldUserActivity, delta); } Thread.sleep(1000); // 1s @@ -320,26 +238,42 @@ return null; } - /* - * @see application.Task#process(java.util.List) + /** + * Add task delta. + * + * @param oldUserActivity time when delta was notified + * @param delta delta to add */ - @Override - protected void process(List<Void> nothing) { + protected void addTaskDelta(long from, long delta) { - // take last notification - // can be notified of many result - // for example, if UI lag... - long currentTime = System.currentTimeMillis(); - long currentDuration = currentTime - taskStartTimestamp + offsetTimeInMs; + long localDelta = delta; - // time can be negative due to adjust caused by idle or hibernate - // just publish 0 in this case - if (currentDuration < 0) { - currentDuration = 0; + // remove time + if (localDelta < 0) { + Date currentDate = new Date(from); + while (localDelta < 0) { + Date todayMidnight = DateUtils.truncate(currentDate, Calendar.DAY_OF_MONTH); + long msToMidnight = currentDate.getTime() - todayMidnight.getTime(); + long toRemove = Math.min(-localDelta, msToMidnight); + dataManager.changeTaskTime(managedTask, currentDate, managedTask.getTime(currentDate) - toRemove); + localDelta += toRemove; + currentDate = DateUtils.addMilliseconds(todayMidnight, -1); + } + } else { + // add time + Date currentDate = new Date(from); + while (localDelta > 0) { + Date today235959 = DateUtils.truncate(currentDate, Calendar.DAY_OF_MONTH); + today235959 = DateUtils.addDays(today235959, 1); + today235959 = DateUtils.addMilliseconds(today235959, -1); + long msToMidnight = today235959.getTime() - currentDate.getTime(); + long toAdd = Math.min(localDelta, msToMidnight); + dataManager.changeTaskTime(managedTask, currentDate, managedTask.getTime(currentDate) + toAdd); + localDelta -= toAdd; + currentDate = DateUtils.addMilliseconds(today235959, 1); + } } - dataManager.changeTaskTime(managedTask, new Date(), currentDuration); - checkTaskAlerts(managedTask); }
participants (1)
-
echatellier@users.chorem.org