github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/common/ipc/shm_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 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 #pragma once 21 #include "common/common.h" 22 #include "common/ipc/shm_base.h" 23 #include "common/ipc/shm_session.h" 24 25 namespace neb { 26 namespace ipc { 27 namespace internal { 28 struct shm_queue_failure : public std::exception { 29 inline shm_queue_failure(const std::string &msg) : m_msg(msg) {} 30 inline const char *what() const throw() { return m_msg.c_str(); } 31 32 protected: 33 std::string m_msg; 34 }; 35 class shm_queue { 36 public: 37 enum element_op_tag { 38 new_object, 39 recycle_object, 40 }; 41 42 shm_queue(const std::string &name, shm_session_base *session, 43 boost::interprocess::managed_shared_memory *shmem, size_t capacity); 44 45 template <typename T> void push_back(T *ptr) { 46 push_back(T::pkg_identifier, ptr); 47 } 48 void push_back(shm_type_id_t type_id, void *ptr); 49 50 template <typename T> void recycle(T *ptr) { 51 boost::interprocess::scoped_lock<boost::interprocess::named_mutex> _l( 52 *m_mutex); 53 if (m_buffer->size() == m_capacity) { 54 m_full_cond->wait(_l); 55 } 56 if (m_buffer->size() >= m_capacity) 57 return; 58 boost::interprocess::managed_shared_memory::handle_t h = 59 m_shmem->get_handle_from_address(ptr); 60 vector_elem_t e; 61 e.m_handle = h; 62 e.m_type = T::pkg_identifier; 63 e.m_op_type = recycle_object; 64 m_buffer->push_back(e); 65 if (m_buffer->size() == 1) { 66 m_empty_cond->notify_one(); 67 } 68 } 69 70 std::tuple<void *, shm_type_id_t, element_op_tag> pop_front(); 71 72 std::tuple<void *, shm_type_id_t, element_op_tag> try_pop_front(); 73 74 size_t size() const; 75 76 void wake_up_if_empty(); 77 size_t empty() const; 78 79 virtual ~shm_queue(); 80 81 void reset(); 82 83 private: 84 std::string mutex_name() { return m_name + ".mutex"; } 85 std::string empty_cond_name() { return m_name + ".empty_cond"; } 86 std::string full_cond_name() { return m_name + ".full_cond"; } 87 88 protected: 89 struct vector_elem_t { 90 boost::interprocess::managed_shared_memory::handle_t m_handle; 91 shm_type_id_t m_type; 92 element_op_tag m_op_type; 93 }; 94 typedef boost::interprocess::allocator< 95 vector_elem_t, 96 boost::interprocess::managed_shared_memory::segment_manager> 97 shmem_allocator_t; 98 typedef boost::interprocess::vector<vector_elem_t, shmem_allocator_t> 99 shm_vector_t; 100 std::string m_name; 101 boost::interprocess::managed_shared_memory *m_shmem; 102 shmem_allocator_t *m_shm_allocator; 103 shmem_allocator_t *m_allocator; 104 105 shm_vector_t *m_buffer; 106 size_t m_capacity; 107 108 std::unique_ptr<boost::interprocess::named_mutex> m_mutex; 109 std::unique_ptr<boost::interprocess::named_condition> m_empty_cond; 110 std::unique_ptr<boost::interprocess::named_condition> m_full_cond; 111 shm_session_base *m_session; 112 }; // end class shm_queue 113 } 114 } 115 }