github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/util/thread_safe_map.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  
    23  namespace neb {
    24  template <typename Key, typename Val, typename Lock = boost::shared_mutex>
    25  class thread_safe_map {
    26  public:
    27    typedef std::map<Key, Val> map_t;
    28    typedef Lock lock_t;
    29    using r_guard_t = boost::shared_lock<lock_t>;
    30    using w_guard_t = std::unique_lock<lock_t>;
    31  
    32    thread_safe_map() = default;
    33  
    34    void insert(const typename map_t::key_type &k,
    35                const typename map_t::mapped_type &v) {
    36      w_guard_t _l(m_mutex);
    37      if (m_map.find(k) != m_map.end()) {
    38        m_map[k] = v;
    39        return;
    40      }
    41      m_map.insert(std::make_pair(k, v));
    42    }
    43  
    44    bool insert_if_not_exist(const typename map_t::key_type &k,
    45                             const typename map_t::mapped_type &v) {
    46      w_guard_t _l(m_mutex);
    47      if (m_map.find(k) != m_map.end()) {
    48        m_map[k] = v;
    49        return false;
    50      }
    51      m_map.insert(std::make_pair(k, v));
    52      return true;
    53    }
    54  
    55    void erase(const typename map_t::key_type &k) {
    56      w_guard_t _l(m_mutex);
    57      auto it = m_map.find(k);
    58      if (it != m_map.end()) {
    59        m_map.erase(it);
    60      }
    61    }
    62  
    63    std::pair<bool, typename map_t::mapped_type>
    64    try_get_and_update_val(const typename map_t::key_type &k,
    65                           const typename map_t::mapped_type &v) {
    66      w_guard_t _l(m_mutex);
    67      auto ret = try_get_val(k);
    68      insert(k, v);
    69      return ret;
    70    }
    71  
    72    std::pair<bool, typename map_t::mapped_type>
    73    try_get_val(const typename map_t::key_type &k) {
    74      r_guard_t _l(m_mutex);
    75      if (m_map.find(k) == m_map.end()) {
    76        return std::make_pair(false, typename map_t::mapped_type());
    77      }
    78      auto ret = m_map.find(k)->second;
    79      return std::make_pair(true, ret);
    80    }
    81  
    82    std::pair<bool, typename map_t::value_type>
    83    try_lower_than(const typename map_t::key_type &k) {
    84      r_guard_t _l(m_mutex);
    85      if (m_map.empty() || k < m_map.begin()->first) {
    86        return std::make_pair(false, typename map_t::value_type());
    87      }
    88      auto it = m_map.upper_bound(k);
    89      it--;
    90      auto ret = *it;
    91      return std::make_pair(true, ret);
    92    }
    93  
    94    typename map_t::value_type begin() {
    95      r_guard_t _l(m_mutex);
    96      auto ret = m_map.begin();
    97      return *ret;
    98    }
    99  
   100    typename map_t::value_type end() {
   101      r_guard_t _l(m_mutex);
   102      auto ret = m_map.end();
   103      return *ret;
   104    }
   105  
   106    bool exist(const typename map_t::key_type &k) {
   107      r_guard_t _l(m_mutex);
   108      return m_map.find(k) != m_map.end();
   109    }
   110  
   111    size_t size() const {
   112      r_guard_t _l(m_mutex);
   113      return m_map.size();
   114    }
   115  
   116    bool empty() const {
   117      r_guard_t _l(m_mutex);
   118      return m_map.empty();
   119    }
   120  
   121    void clear() {
   122      w_guard_t _l(m_mutex);
   123      m_map.clear();
   124    }
   125  
   126  private:
   127    map_t m_map;
   128    mutable lock_t m_mutex;
   129  };
   130  } // namespace neb