muduo Blocking queue

文章目录
  1. 1. 条件变量的使用
    1. 1.0.1. 对于 wait 端
    2. 1.0.2. 对于 signal/broadcast 端
  • 2. 代码大赏
  • 3. 参考资料
  • 条件变量的使用

    对于 wait 端

    1. 必须与 mutex 一起使用,该布尔表达式的读写需受此 mutex 保护。
    2. 在 mutex 已上锁的时候才能调用 wait。
    3. 把判断布尔条件和 wait() 放在 while 循环中。 (不用 if 的原因 spurious wakeup)

    对于 signal/broadcast 端

    1. 不一定要在 mutex 已上锁的情况下调用 signal
    2. 在 signal 之前一般要修改布尔表达式
    3. 修改布尔表达式通常要用 mutex 保护
    4. 注意区分 signal 和 broadcast: broadcast 一般用于表明状态变化,signal 通常用于表明资源可用

    代码大赏

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    // Use of this source code is governed by a BSD-style license
    // that can be found in the License file.
    //
    // Author: Shuo Chen (chenshuo at chenshuo dot com)

    #ifndef MUDUO_BASE_BLOCKINGQUEUE_H
    #define MUDUO_BASE_BLOCKINGQUEUE_H

    #include "muduo/base/Condition.h"
    #include "muduo/base/Mutex.h"

    #include <deque>
    #include <assert.h>

    namespace muduo
    {

    template<typename T>
    class BlockingQueue : noncopyable
    {
    public:
    BlockingQueue()
    : mutex_(),
    notEmpty_(mutex_),
    queue_()
    {
    }

    void put(const T& x)
    {
    MutexLockGuard lock(mutex_);
    queue_.push_back(x);
    notEmpty_.notify(); // wait morphing saves us
    // http://www.domaigne.com/blog/computing/condvars-signal-with-mutex-locked-or-not/
    }

    void put(T&& x)
    {
    MutexLockGuard lock(mutex_);
    queue_.push_back(std::move(x));
    notEmpty_.notify();
    }

    T take()
    {
    MutexLockGuard lock(mutex_);
    // always use a while-loop, due to spurious wakeup
    while (queue_.empty())
    {
    notEmpty_.wait(); // 这一步会原子地 unlock mutex 并进入等待,不会与 put 思索, 执行完毕时会自动重新加锁。
    }
    assert(!queue_.empty());
    T front(std::move(queue_.front()));
    queue_.pop_front();
    return front;
    }

    size_t size() const
    {
    MutexLockGuard lock(mutex_);
    return queue_.size();
    }

    private:
    mutable MutexLock mutex_;
    Condition notEmpty_ GUARDED_BY(mutex_);
    std::deque<T> queue_ GUARDED_BY(mutex_);
    };

    } // namespace muduo

    #endif // MUDUO_BASE_BLOCKINGQUEUE_H

    参考资料

    • BlockingQueue
    • linux 多线程服务端编程–使用 muduo c++ 网络库