/** * Cancel a previously scheduled timer event. * * @param target Object whose event this is. */ boolean cancelTimeout(TimerWatcher target) { synchronized (myLock) { TimerQEntry entry; TimerQEntry previous; if (myTopEntry == null) { return false; } if (myTopEntry.myTarget == target) { entry = myTopEntry; myTopEntry = myTopEntry.myNext; } else { previous = myTopEntry; entry = myTopEntry.myNext; while (entry != null) { if (entry.myTarget == target) { previous.myNext = entry.myNext; break; } previous = entry; entry = entry.myNext; } } if (entry != null) { entry.myNext = null; return true; } else { return false; } } }
/** Sort the timer queue entries in order of time. Called when one or more entries are altered. */ private void orderEntries() { TimerQEntry newEntry = null; synchronized (myLock) { if (myTopEntry == null) { return; } while (myTopEntry != null) { TimerQEntry winner = myTopEntry; TimerQEntry entry = winner.myNext; TimerQEntry before = null; TimerQEntry prev = winner; while (entry != null) { if (entry.myWhen > winner.myWhen) { before = prev; winner = entry; } prev = entry; entry = entry.myNext; } if (before != null) { before.myNext = winner.myNext; } else { myTopEntry = winner.myNext; } winner.myNext = newEntry; newEntry = winner; } } myTopEntry = newEntry; }
/** * Insert a new event into the timer queue (in order). * * @param newEntry A TimerQEntry describing the new event. */ private void insertEntry(TimerQEntry newEntry) { synchronized (myLock) { TimerQEntry previous = null; TimerQEntry entry = myTopEntry; while (entry != null) { if (newEntry.myWhen <= entry.myWhen) { break; } previous = entry; entry = entry.myNext; } if (previous == null) { newEntry.myNext = myTopEntry; myTopEntry = newEntry; } else { newEntry.myNext = previous.myNext; previous.myNext = newEntry; } } }
/** * The actual guts of the timer thread: Look for the next event on the timer queue. Wait until the * indicated time. Process the event and any others that may now be relevent. Repeat. */ private void runloop() { long time; boolean reorder; FlexList notifies = null; TimerQEntry entry; TimerQEntry previous; synchronized (myLock) { if (myTopEntry != null) { time = (myTopEntry.myWhen - System.currentTimeMillis()) | 1; // Avoid 0 since will wait forever } else { time = 0; } } synchronized (myLock) { try { if (0 <= time) { myLock.wait(time); } } catch (Exception e) { // No problem - something added or cancelled from queue } } synchronized (myLock) { // Only do the next bunch 'o stuff if this timer is still running if (myRunning) { // Timer fired, check each element to see if it is time long now = System.currentTimeMillis(); boolean needToReorder = false; entry = myTopEntry; previous = null; while (entry != null) { if (entry.myWhen <= now) { if (notifies == null) { notifies = FlexList.make(5); } notifies.push(entry); if (entry.myRepeat) { needToReorder = true; entry.myWhen = entry.myWhen + entry.myDelta; long deltoid = entry.myDelta * FUDGE; if ((entry.myWhen + deltoid) < now) { // Round up in increments of entry.myDelta to // maintain timebase, but myDelta from "now" // "now" being rounded up to the timebase long dist = (now - entry.myWhen) + entry.myDelta; dist = (dist / entry.myDelta) * entry.myDelta; entry.myWhen = entry.myWhen + dist; } previous = entry; } else { // Remove it if (previous == null) { myTopEntry = entry.myNext; } else { previous.myNext = entry.myNext; } } entry = entry.myNext; } else { break; } } if (needToReorder) { orderEntries(); } } } if (!myRunning) { return; } // Enumerate over notifies and notify them if (notifies != null) { int count = notifies.size(); int i = 0; while (myRunning && i < count) { entry = (TimerQEntry) notifies.get(i++); TimerWatcher target = entry.myTarget; try { target.handleTimeout(); } catch (Exception e) { System.err.println("Exception in HandleTimeout meth"); ExceptionMgr.reportException(e); } } } }