timer: add unsafe callbacks option

Using unsafe callbacks drops the lock between invocations of event
callbacks. It is useful under some circumstances, but the user must take
caution. See the comment in Timer.h for full details.

Signed-off-by: Mike Ryan <mike.ryan@inktank.com>
This commit is contained in:
Mike Ryan 2012-09-14 10:30:17 -07:00
parent 4015343f27
commit a6b0d55b2b
2 changed files with 19 additions and 3 deletions

View File

@ -45,10 +45,11 @@ public:
typedef std::multimap < utime_t, Context *> scheduled_map_t;
typedef std::map < Context*, scheduled_map_t::iterator > event_lookup_map_t;
SafeTimer::SafeTimer(CephContext *cct_, Mutex &l)
SafeTimer::SafeTimer(CephContext *cct_, Mutex &l, bool safe_callbacks)
: cct(cct_), lock(l),
safe_callbacks(safe_callbacks),
thread(NULL),
stopping(false)
stopping(false)
{
}
@ -99,8 +100,12 @@ void SafeTimer::timer_thread()
schedule.erase(p);
ldout(cct,10) << "timer_thread executing " << callback << dendl;
if (!safe_callbacks)
lock.Unlock();
callback->finish(0);
delete callback;
if (!safe_callbacks)
lock.Lock();
}
ldout(cct,20) << "timer_thread going to sleep" << dendl;

View File

@ -33,6 +33,7 @@ class SafeTimer
CephContext *cct;
Mutex& lock;
Cond cond;
bool safe_callbacks;
friend class SafeTimerThread;
SafeTimerThread *thread;
@ -47,7 +48,17 @@ class SafeTimer
void dump(const char *caller = 0) const;
public:
SafeTimer(CephContext *cct, Mutex &l);
/* Safe callbacks determines whether callbacks are called with the lock
* held.
*
* safe_callbacks = true (default option) guarantees that a cancelled
* event's callback will never be called.
*
* Under some circumstances, holding the lock can cause lock cycles.
* If you are able to relax requirements on cancelled callbacks, then
* setting safe_callbacks = false eliminates the lock cycle issue.
* */
SafeTimer(CephContext *cct, Mutex &l, bool safe_callbacks=true);
~SafeTimer();
/* Call with the event_lock UNLOCKED.