summaryrefslogtreecommitdiff
path: root/lib/common/Timer.cpp
diff options
context:
space:
mode:
authorChris Wilson <chris+github@qwirx.com>2006-12-13 21:54:16 +0000
committerChris Wilson <chris+github@qwirx.com>2006-12-13 21:54:16 +0000
commit5884ded87261d294842bdcceeca84411a9919ec8 (patch)
treeef1312a0be2c6e9cbb135df16e3e0ddc604a4b82 /lib/common/Timer.cpp
parentf996ca761339f4c4b5c32604e1800e683aa40930 (diff)
Fix more deadlocks by minimising the amount of stuff that the signal
handler does. (refs #3, refs #9)
Diffstat (limited to 'lib/common/Timer.cpp')
-rw-r--r--lib/common/Timer.cpp62
1 files changed, 30 insertions, 32 deletions
diff --git a/lib/common/Timer.cpp b/lib/common/Timer.cpp
index 10365e03..de01f9f0 100644
--- a/lib/common/Timer.cpp
+++ b/lib/common/Timer.cpp
@@ -126,14 +126,16 @@ void Timers::Reschedule()
{
ASSERT(spTimers);
- // Set the reschedule-needed flag to false before we start.
+ // Clear the reschedule-needed flag to false before we start.
// If a timer event occurs while we are scheduling, then we
// may or may not need to reschedule again, but this way
// we will do it anyway.
sRescheduleNeeded = false;
- // scan for and remove expired timers, which requires
- // us to restart the scan each time we remove one.
+ box_time_t timeNow = GetCurrentBoxTime();
+
+ // scan for, trigger and remove expired timers. Removal requires
+ // us to restart the scan each time, due to std::vector semantics.
bool restart = true;
while (restart)
{
@@ -143,19 +145,36 @@ void Timers::Reschedule()
i != spTimers->end(); i++)
{
Timer& rTimer = **i;
- if (rTimer.HasExpired())
+ int64_t timeToExpiry = rTimer.GetExpiryTime() - timeNow;
+
+ if (timeToExpiry <= 0)
{
+ TRACE3("%d.%d: timer %p has expired, "
+ "triggering it\n",
+ (int)(timeNow / 1000000),
+ (int)(timeNow % 1000000),
+ *i);
+ rTimer.OnExpire();
spTimers->erase(i);
restart = true;
break;
}
+ else
+ {
+ TRACE5("%d.%d: timer %p has not expired, "
+ "triggering in %d.%d seconds\n",
+ (int)(timeNow / 1000000),
+ (int)(timeNow % 1000000),
+ *i,
+ (int)(timeToExpiry / 1000000),
+ (int)(timeToExpiry % 1000000));
+ }
}
}
// Now the only remaining timers should all be in the future.
// Scan to find the next one to fire (earliest deadline).
- box_time_t timeNow = GetCurrentBoxTime();
int64_t timeToNextEvent = 0;
for (std::vector<Timer*>::iterator i = spTimers->begin();
@@ -199,37 +218,17 @@ void Timers::Reschedule()
//
// Function
// Name: static void Timers::SignalHandler(unused)
-// Purpose: Called as signal handler. Signals any timers which
-// are due or overdue, removes them from the set,
-// and requests a reschedule event. The actual
-// reschedule will happen next time someone calls
-// Timer::HasExpired(), which may be rather late,
-// but we can't do it from here, in signal context.
+// Purpose: Called as signal handler. Nothing is safe in a signal
+// handler, not even traversing the list of timers, so
+// just request a reschedule in future, which will do
+// that for us, and trigger any expired timers at that
+// time.
// Created: 5/11/2006
//
// --------------------------------------------------------------------------
void Timers::SignalHandler(int iUnused)
{
- ASSERT(spTimers);
-
- box_time_t timeNow = GetCurrentBoxTime();
-
- std::vector<Timer*> timersCopy = *spTimers;
-
- for (std::vector<Timer*>::iterator i = timersCopy.begin();
- i != timersCopy.end(); i++)
- {
- Timer& rTimer = **i;
- ASSERT(!rTimer.HasExpired());
-
- int64_t timeToExpiry = rTimer.GetExpiryTime() - timeNow;
-
- if (timeToExpiry <= 0)
- {
- rTimer.OnExpire();
- }
- }
-
+ // ASSERT(spTimers);
Timers::RequestReschedule();
}
@@ -356,5 +355,4 @@ void Timer::OnExpire()
#endif
mExpired = true;
- Timers::Remove(*this);
}