Beispiel #1
0
        /*! 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);
            }
        }
Beispiel #2
0
        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();
        }
Beispiel #3
0
        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();
            }
        }