handy源码阅读(三):SafeQueue类

SafeQueue类继承与信号量mutex(用于加锁),nonocopyable

定义如下:

template <typename T>
struct SafeQueue : private std::mutex, private noncopyable {
  static const int wait_infinite = std::numeric_limits<int>::max();

  SafeQueue(size_t capacity = 0) : capacity_(capacity), exit_(false) {}
  bool push(T&& v)
  T pop_wait(int waitMs = wait_infinite);
  bool pop_wait(T* v, int waitMs = wait_infinite);

  size_t size();
  void exit();
  bool exited() {  return exit_; }

private:
  std::list<T> items_;
  std::condition_variable ready_;
  size_t capacity_;
  std::atomic<bool> exit_;
  void wait_ready(std::unique_lock<std::mutex>& lk, int waitMs); 
};

该类可以安全的添加和删除任务,类内部使用容器list来存储具体的任务,具有退出状态:exit_,取出任务时可以设定超时时间。

其中Task的定义为:typedef std::function<void()> Task;  Task为返回值为空的函数对象

SafeQueue的具体实现如下:

template <typename T>
size_t SafeQueue<T>::size() {
  std::lock_guard(std::mutex) lk(*this);
  return items_.size();
}

template <typename T>
void SafeQueue<T>::exit() {
  exit_ = true;
  std::lock_guard<std::mutex> lk(*this);
  ready_.notify_all();
}

template <typename T>
bool SafeQueue<T>::push(T&& v) {
  std::lock_guard<std::mutex> lk(*this);
  if (exit_ || (capacity_ && items_.size() >= capacity_)) {
    return false;
  }

  items_.push_back(std::move(v));
  ready_.notify_one();
  return true;
}

template <typename T>
void SafeQueue<T>::wait_ready(std::unique_lock<std::mutex>& lk, int waitMs) {
  if (exit_ || !items_.empty()) {
    return;
  }
  if (waitMs == wait_infinite) {
    ready_.wait(lk, [this] {  return exit_ || !items_.empty();  });
  } else if (waitMs > 0) {
    auto tp = std::chrono::steady_clock::now() + std::chrono::milliseconds(waitMs);
  while (ready_.wait_until(lk, tp) != std::cv_status::timeout && items_.empty() && !exit_) {
  }
  }
}

template <typename T>
bool SafeQueue<T>::pop_wait(T* v, int waitMs) {
  std::unique_lock<std::mutex> lk(*this);
  wait_ready(lk, waitMs);
  if (items_.empty()) {
    return false;
  }

  *v = std::move(items_.front());
  items_.pop_front();
  return true;
}

template <typename T>
T SafeQueue<T>::pop_wait(int waitMs) {
  std::unique_lock<std::mutex> lk(*this);
  wait_ready(lk, waitMs);
  if (items_.empty()) {
    return T();
  }
  T r = std::move(items_.front());
  items_.pop_front();
  return r;
}

 

posted @ 2019-09-19 19:29  c++11  阅读(510)  评论(0编辑  收藏  举报