Some AIFrameTimer code cleanup and comment fixes.

This commit is contained in:
Aleric Inglewood
2011-08-14 15:42:46 +02:00
parent 5945793031
commit 3de99315e2
2 changed files with 16 additions and 13 deletions

View File

@@ -45,8 +45,7 @@ LLMutex AIFrameTimer::sMutex;
// 3) The object is inserted in the list (operator<(AIRunningFrameTimer const&, AIRunningFrameTimer const&)). // 3) The object is inserted in the list (operator<(AIRunningFrameTimer const&, AIRunningFrameTimer const&)).
// 4) The object is initialized (AIRunningFrameTimer::init). // 4) The object is initialized (AIRunningFrameTimer::init).
// 5) The lock is released. // 5) The lock is released.
// This assures that the object is not yet shared at the moment // This assures that the object is not yet shared at the moment that it is initialized.
// that it is initialized (assignment to mConnection is not thread-safe).
void AIFrameTimer::create(F64 expiration, signal_type::slot_type const& slot) void AIFrameTimer::create(F64 expiration, signal_type::slot_type const& slot)
{ {
@@ -60,17 +59,25 @@ void AIFrameTimer::create(F64 expiration, signal_type::slot_type const& slot)
void AIFrameTimer::cancel(void) void AIFrameTimer::cancel(void)
{ {
// In order to stop us from returning from cancel() while
// the callback function is being called (which is done
// in AIFrameTimer::handleExpiration after obtaining the
// mHandle.mMutex lock), we start with trying to obtain
// it here and as such wait till the callback function
// returned.
mHandle.mMutex.lock(); mHandle.mMutex.lock();
// Next we have to grab this lock in order to stop
// AIFrameTimer::handleExpiration from even entering
// in the case we manage to get it first.
sMutex.lock(); sMutex.lock();
mHandle.mMutex.unlock();
if (mHandle.mRunningTimer != sTimerList.end()) if (mHandle.mRunningTimer != sTimerList.end())
{ {
timer_list_type::iterator running_timer = mHandle.mRunningTimer; sTimerList.erase(mHandle.mRunningTimer);
mHandle.mRunningTimer = sTimerList.end(); mHandle.mRunningTimer = sTimerList.end();
sTimerList.erase(running_timer);
sNextExpiration = sTimerList.empty() ? NEVER : sTimerList.begin()->expiration(); sNextExpiration = sTimerList.empty() ? NEVER : sTimerList.begin()->expiration();
} }
sMutex.unlock(); sMutex.unlock();
mHandle.mMutex.unlock();
} }
void AIFrameTimer::handleExpiration(F64 current_frame_time) void AIFrameTimer::handleExpiration(F64 current_frame_time)
@@ -125,9 +132,8 @@ void AIFrameTimer::handleExpiration(F64 current_frame_time)
// handle.mRunningTimer equals sTimerList.end(), exits the function and // handle.mRunningTimer equals sTimerList.end(), exits the function and
// (possibly) deletes the callback object. // (possibly) deletes the callback object.
// //
// Note that if the other thread actually obtained the sMutex and // Note that if the other thread actually obtained the sMutex then we
// released handle.mMutex again, then we can't be here: this is still // can't be here: this is still inside the critical area of sMutex.
// inside the critical area of sMutex.
if (handle.mMutex.tryLock()) // If this fails then another thread is in the process of cancelling this timer, so do nothing. if (handle.mMutex.tryLock()) // If this fails then another thread is in the process of cancelling this timer, so do nothing.
{ {
sMutex.unlock(); sMutex.unlock();

View File

@@ -93,7 +93,7 @@ class LL_COMMON_API AIFrameTimer
// and cancellation by the thread owning the AIFrameTimer (by calling // and cancellation by the thread owning the AIFrameTimer (by calling
// AIFrameTimer::cancel). // AIFrameTimer::cancel).
// Construction for a not-running timer. // Constructor for a not-running timer.
Handle(void) : mRunningTimer(sTimerList.end()) { } Handle(void) : mRunningTimer(sTimerList.end()) { }
// Actual initialization used by AIFrameTimer::create. // Actual initialization used by AIFrameTimer::create.
@@ -113,10 +113,7 @@ class LL_COMMON_API AIFrameTimer
Handle mHandle; Handle mHandle;
public: public:
// Construct an AIFrameTimer that is not initialized. // Construct an AIFrameTimer that is not running.
//
// The call to end() is deliberately not put inside a critical area because it's a read-only
// operation on something that is never written to while there are threads.
AIFrameTimer(void) { } AIFrameTimer(void) { }
// Construction of a running AIFrameTimer with expiration time expiration in seconds, and callback slot. // Construction of a running AIFrameTimer with expiration time expiration in seconds, and callback slot.