github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/util/wakeable_queue.h (about)

     1  // Copyright (C) 2018 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or
     6  // modify
     7  // it under the terms of the GNU General Public License as published by
     8  // the Free Software Foundation, either version 3 of the License, or // (at your
     9  // option) any later version.
    10  //
    11  // the go-nebulas library is distributed in the hope that it will be useful,
    12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  // GNU General Public License for more details.
    15  //
    16  // You should have received a copy of the GNU General Public License
    17  // along with the go-nebulas library.  If not, see
    18  // <http://www.gnu.org/licenses/>.
    19  //
    20  #pragma once
    21  #include "common/common.h"
    22  #include <condition_variable>
    23  #include <queue>
    24  
    25  namespace neb {
    26  namespace util {
    27  
    28  template <typename T> class wakeable_queue {
    29  public:
    30    typedef std::queue<T> queue_t;
    31    wakeable_queue() = default;
    32  
    33    void push_back(const typename queue_t::value_type &op) {
    34      std::unique_lock<std::mutex> _l(m_mutex);
    35      bool was_empty = m_queue.empty();
    36      m_queue.push(op);
    37      _l.unlock();
    38      if (was_empty) {
    39        m_cond_var.notify_all();
    40      }
    41    }
    42  
    43    std::pair<bool, typename queue_t::value_type> pop_front() {
    44      std::unique_lock<std::mutex> _l(m_mutex);
    45      bool is_empty = m_queue.empty();
    46      if (is_empty) {
    47        m_cond_var.wait(_l);
    48      }
    49      if (m_queue.empty()) {
    50        return std::make_pair(false, typename queue_t::value_type());
    51      }
    52      auto ret = m_queue.front();
    53      m_queue.pop();
    54      return std::make_pair(true, ret);
    55    }
    56  
    57    std::pair<bool, typename queue_t::value_type> try_pop_front() {
    58      std::unique_lock<std::mutex> _l(m_mutex);
    59      if (m_queue.empty()) {
    60        return std::make_pair(false, typename queue_t::value_type());
    61      }
    62      auto ret = m_queue.front();
    63      m_queue.pop();
    64      return std::make_pair(true, ret);
    65    }
    66  
    67    size_t size() const {
    68      std::unique_lock<std::mutex> _l(m_mutex);
    69      return m_queue.size();
    70    }
    71  
    72    bool empty() const {
    73      std::unique_lock<std::mutex> _l(m_mutex);
    74      return m_queue.empty();
    75    }
    76  
    77    void wake_up_if_empty() {
    78      std::unique_lock<std::mutex> _l(m_mutex);
    79      if (m_queue.empty()) {
    80        _l.unlock();
    81        m_cond_var.notify_one();
    82      }
    83    }
    84  
    85  protected:
    86    queue_t m_queue;
    87    mutable std::mutex m_mutex;
    88    std::condition_variable m_cond_var;
    89  };
    90  } // namespace util
    91  
    92  } // namespace neb