/*! Decrements lock counter and unlocks monitor if counter is 0; * throws EBUSY if lock counter is not 0 */ void unlock() { gu::Lock lock(mutex_); assert (locked_ >= 0); if (0 == locked_) { assert (locked_ != 0); gu_throw_error(EALREADY) << "Attempt to unlock an already unlocked monitor"; } locked_--; if (0 == locked_) { update_last_left(); drain_seqno_ = LLONG_MAX; cond_.broadcast(); log_debug << "Unlocked local monitor at " << last_left_; } else { gu_throw_error(EBUSY); } }
void drain(wsrep_seqno_t seqno) { gu::Lock lock(mutex_); while (drain_seqno_ != GU_LLONG_MAX) { lock.wait(cond_); } drain_common(seqno, lock); // there can be some stale canceled entries update_last_left(); drain_seqno_ = GU_LLONG_MAX; cond_.broadcast(); }
void post_leave(const C& obj, gu::Lock& lock) { const wsrep_seqno_t obj_seqno(obj.seqno()); const size_t idx(indexof(obj_seqno)); if (last_left_ + 1 == obj_seqno) // we're shrinking window { process_[idx].state_ = Process::S_IDLE; last_left_ = obj_seqno; process_[idx].wait_cond_.broadcast(); update_last_left(); oool_ += (last_left_ > obj_seqno); // wake up waiters that may remain above us (last_left_ // now is max) wake_up_next(); } else { process_[idx].state_ = Process::S_FINISHED; } process_[idx].obj_ = 0; assert((last_left_ >= obj_seqno && process_[idx].state_ == Process::S_IDLE) || process_[idx].state_ == Process::S_FINISHED); assert(last_left_ != last_entered_ || process_[indexof(last_left_)].state_ == Process::S_IDLE); if ((last_left_ >= obj_seqno) || // - occupied window shrinked (last_left_ >= drain_seqno_)) // - this is to notify drain that // we reached drain_seqno_ { cond_.broadcast(); } }