github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/common/ipc/shm_bookkeeper.cpp (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 9 // (at your 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 #include "common/ipc/shm_bookkeeper.h" 21 #include "common/common.h" 22 #include "common/ipc/shm_base.h" 23 24 namespace neb { 25 namespace ipc { 26 void clean_bookkeeper_env(const std::string &name) { 27 boost::interprocess::shared_memory_object::remove(name.c_str()); 28 boost::interprocess::named_mutex::remove((name + ".mutex").c_str()); 29 } 30 31 namespace internal { 32 33 size_t bookkeeper_mem_size = 64 * 1024; 34 35 shm_bookkeeper::shm_bookkeeper(const std::string &name) : m_name(name) { 36 try { 37 m_segment = std::unique_ptr<boost::interprocess::managed_shared_memory>( 38 new boost::interprocess::managed_shared_memory( 39 boost::interprocess::open_or_create, m_name.c_str(), 40 bookkeeper_mem_size)); 41 42 m_allocator = std::unique_ptr<map_allocator_t>( 43 new map_allocator_t(m_segment->get_segment_manager())); 44 45 m_mutex = std::unique_ptr<boost::interprocess::named_mutex>( 46 new boost::interprocess::named_mutex( 47 boost::interprocess::open_or_create, mutex_name().c_str())); 48 49 m_map = m_segment->find_or_construct<map_t>(mem_name().c_str())( 50 std::less<char_string_t>(), *m_allocator); 51 } catch (const std::exception &e) { 52 m_mutex.reset(); 53 m_segment.reset(); 54 throw shm_init_failure(std::string("shm_bookkeeper, ") + 55 std::string(typeid(e).name()) + " : " + e.what()); 56 } 57 } 58 void shm_bookkeeper::reset() { 59 if (!m_mutex) 60 return; 61 //! We may fail to acquire m_mutex, thus, we just don't. 62 m_mutex->try_lock(); 63 64 for (auto it = m_map->begin(); it != m_map->end(); ++it) { 65 auto first = it->first; 66 auto second = it->second; 67 tag_counter_t tt; 68 tt.set_data(second); 69 if (tt.type() == tag_counter_t::boost_mutex) { 70 boost::interprocess::named_mutex::remove(first.c_str()); 71 } else if (tt.type() == tag_counter_t::boost_semaphore) { 72 boost::interprocess::named_semaphore::remove(first.c_str()); 73 } else if (tt.type() == tag_counter_t::boost_condition) { 74 boost::interprocess::named_condition::remove(first.c_str()); 75 } 76 } 77 78 m_mutex->unlock(); 79 80 boost::interprocess::named_mutex::remove(mutex_name().c_str()); 81 boost::interprocess::shared_memory_object::remove(m_name.c_str()); 82 83 // LOG(INFO) << "realloc local vars"; 84 // m_segment = std::unique_ptr<boost::interprocess::managed_shared_memory>( 85 // new boost::interprocess::managed_shared_memory( 86 // boost::interprocess::open_or_create, m_name.c_str(), 87 // bookkeeper_mem_size)); 88 89 // m_allocator = std::unique_ptr<map_allocator_t>( 90 // new map_allocator_t(m_segment->get_segment_manager())); 91 92 // m_mutex = std::unique_ptr<boost::interprocess::named_mutex>( 93 // new boost::interprocess::named_mutex(boost::interprocess::open_or_create, 94 // mutex_name().c_str())); 95 96 // m_map = m_segment->find_or_construct<map_t>(mem_name().c_str())( 97 // std::less<char_string_t>(), *m_allocator); 98 } 99 100 void shm_bookkeeper::acquire(const std::string &name, 101 const std::function<void()> &action) { 102 acquire(name, action, tag_counter_t::other_unknown); 103 } 104 105 void shm_bookkeeper::acquire(const std::string &name, 106 const std::function<void()> &action, 107 uint8_t type) { 108 boost::interprocess::scoped_lock<boost::interprocess::named_mutex> _l( 109 *m_mutex); 110 action(); 111 char_string_t cs(name.c_str(), *m_allocator); 112 if (m_map->find(cs) == m_map->end()) { 113 tag_counter_t tt; 114 tt.set_type(static_cast<tag_counter_t::type_tag>(type)); 115 tt.set_counter(1); 116 m_map->insert(std::pair<const char_string_t, uint64_t>(cs, tt.data())); 117 } else { 118 tag_counter_t tt; 119 tt.set_data(m_map->operator[](cs)); 120 tt.set_counter(tt.counter() + 1); 121 m_map->operator[](cs) = tt.data(); 122 } 123 } 124 125 void shm_bookkeeper::release(const std::string &name, 126 const std::function<void()> &action) { 127 boost::interprocess::scoped_lock<boost::interprocess::named_mutex> _l( 128 *m_mutex); 129 130 char_string_t cs(name.c_str(), *m_allocator); 131 if (m_map->find(cs) == m_map->end()) { 132 return; 133 } 134 tag_counter_t tt; 135 tt.set_data(m_map->operator[](cs)); 136 tt.set_counter(tt.counter() - 1); 137 m_map->operator[](cs) = tt.data(); 138 if (tt.counter() == 0) { 139 m_map->erase(cs); 140 action(); 141 } 142 } 143 std::unique_ptr<boost::interprocess::named_mutex> 144 shm_bookkeeper::acquire_named_mutex(const std::string &name) { 145 std::unique_ptr<boost::interprocess::named_mutex> ret; 146 acquire(name, 147 [&ret, name]() { 148 ret = std::unique_ptr<boost::interprocess::named_mutex>( 149 new boost::interprocess::named_mutex( 150 boost::interprocess::open_or_create, name.c_str())); 151 }, 152 tag_counter_t::boost_mutex); 153 return ret; 154 } 155 156 void shm_bookkeeper::release_named_mutex(const std::string &name) { 157 release(name, 158 [name]() { boost::interprocess::named_mutex::remove(name.c_str()); }); 159 } 160 161 std::unique_ptr<boost::interprocess::named_semaphore> 162 shm_bookkeeper::acquire_named_semaphore(const std::string &name) { 163 std::unique_ptr<boost::interprocess::named_semaphore> ret; 164 acquire(name, 165 [&ret, name]() { 166 ret = std::unique_ptr<boost::interprocess::named_semaphore>( 167 new boost::interprocess::named_semaphore( 168 boost::interprocess::open_or_create, name.c_str(), 0)); 169 }, 170 tag_counter_t::boost_semaphore); 171 return ret; 172 } 173 174 void shm_bookkeeper::release_named_semaphore(const std::string &name) { 175 release(name, [name]() { 176 boost::interprocess::named_semaphore::remove(name.c_str()); 177 }); 178 } 179 180 std::unique_ptr<boost::interprocess::named_condition> 181 shm_bookkeeper::acquire_named_condition(const std::string &name) { 182 std::unique_ptr<boost::interprocess::named_condition> ret; 183 acquire(name, 184 [&ret, name]() { 185 ret = std::unique_ptr<boost::interprocess::named_condition>( 186 new boost::interprocess::named_condition( 187 boost::interprocess::open_or_create, name.c_str())); 188 }, 189 tag_counter_t::boost_condition); 190 return ret; 191 } 192 void shm_bookkeeper::release_named_condition(const std::string &name) { 193 release(name, [name]() { 194 boost::interprocess::named_condition::remove(name.c_str()); 195 }); 196 } 197 } 198 } 199 } // namespace neb