}
void
-Mutex::preUnlockAction() {
+Mutex::preUnlockAction(bool throw_ok) {
if (impl_->locked_count == 0) {
- isc_throw(isc::InvalidOperation, "Unlock attempt for unlocked mutex");
+ if (throw_ok) {
+ isc_throw(isc::InvalidOperation,
+ "Unlock attempt for unlocked mutex");
+ } else {
+ assert(false);
+ }
}
--impl_->locked_count;
}
void
Mutex::unlock() {
assert(impl_ != NULL);
- preUnlockAction(); // Only in debug mode
+ preUnlockAction(false); // Only in debug mode. Ensure no throw.
const int result = pthread_mutex_unlock(&impl_->mutex);
assert(result == 0); // This should never be possible
}
void
CondVar::wait(Mutex& mutex) {
- mutex.preUnlockAction(); // Only in debug mode
+ mutex.preUnlockAction(true); // Only in debug mode
const int result = pthread_cond_wait(&impl_->cond_, &mutex.impl_->mutex);
mutex.postLockAction(); // Only in debug mode
// Commonly called before releasing the lock, checking and updating
// internal state for debug.
- void preUnlockAction();
+ //
+ // If throw_ok is true, it throws \c isc::InvalidOperation when the check
+ // fails; otherwise it aborts the process. This parameter must be set
+ // to false if the call to this shouldn't result in an exception (e.g.
+ // when called from a destructor).
+ void preUnlockAction(bool throw_ok);
class Impl;
Impl* impl_;