github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/common/ipc/shm_service.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_queue.h" 23 #include "common/ipc/shm_queue_watcher.h" 24 #include "common/ipc/shm_service_construct_helper.h" 25 #include "common/ipc/shm_service_op_queue.h" 26 #include "common/ipc/shm_service_recv_handler.h" 27 #include "common/ipc/shm_session.h" 28 #include "common/quitable_thread.h" 29 #include "common/util/enable_func_if.h" 30 #include "core/command.h" 31 #include <mutex> 32 #include <thread> 33 #include <type_traits> 34 #include <unordered_map> 35 36 namespace neb { 37 namespace ipc { 38 39 namespace internal { 40 class shm_service_base : public quitable_thread { 41 public: 42 shm_service_base(shm_role role, const std::string &shm_name, 43 const std::string &shm_in_name, 44 const std::string &shm_out_name, size_t mem_size, 45 size_t shm_in_capacity, size_t shm_out_capacity); 46 virtual ~shm_service_base(); 47 48 template <typename T, typename... ARGS> T *construct(ARGS... args) { 49 if (!m_shmem) { 50 throw shm_service_failure("no shared memory"); 51 } 52 return m_constructer->construct<T>(args...); 53 } 54 55 template <typename T> void destroy(T *ptr) { m_constructer->destroy(ptr); } 56 57 template <typename T> void push_back(T *ptr) { 58 m_constructer->push_back(ptr); 59 } 60 61 template <typename T, typename Func> void add_handler(Func &&f) { 62 m_recv_handler->add_handler<T>(f); 63 } 64 65 void init_local_env(); 66 67 //! this will block the current thread. 68 void run(); 69 70 void reset(); 71 72 inline shm_session_base *session() { return m_session.get(); } 73 inline char_allocator_t &char_allocator() { return *m_char_allocator; } 74 inline default_allocator_t &default_allocator() { 75 return *m_default_allocator; 76 } 77 78 template <typename T> void schedule_task_in_service_thread(T &&func) { 79 auto task = 80 std::shared_ptr<shm_service_op_base>(new shm_service_op_general(func)); 81 m_op_queue->push_back(task); 82 } 83 84 private: 85 void init_local_interprocess_var(); 86 87 virtual void thread_func(); 88 89 inline std::string semaphore_name() const { 90 return m_shm_name + std::string(".quit_semaphore"); 91 } 92 93 inline std::string mutex_name() const { 94 return m_shm_name + std::string(".mutex"); 95 } 96 97 protected: 98 shm_role m_role; 99 size_t m_mem_size; 100 size_t m_shm_in_capacity; 101 size_t m_shm_out_capacity; 102 std::string m_shm_name; 103 std::string m_shm_in_name; 104 std::string m_shm_out_name; 105 boost::interprocess::managed_shared_memory *m_shmem; 106 shm_queue *m_in_buffer; 107 shm_queue *m_out_buffer; 108 std::unique_ptr<shm_session_base> m_session; 109 std::unique_ptr<shm_service_op_queue> m_op_queue; 110 std::unique_ptr<shm_service_construct_helper> m_constructer; 111 std::unique_ptr<shm_service_recv_handler> m_recv_handler; 112 std::unique_ptr<shm_queue_watcher> m_queue_watcher; 113 std::unique_ptr<char_allocator_t> m_char_allocator; 114 std::unique_ptr<default_allocator_t> m_default_allocator; 115 }; // end class shm_service_base 116 } 117 118 template <size_t S> 119 class shm_service_server : public internal::shm_service_base { 120 public: 121 shm_service_server(const std::string &name, size_t in_obj_max_count, 122 size_t out_obj_max_count) 123 : internal::shm_service_base( 124 role_server, name, 125 internal::shm_other_side_role<shm_server>::type::role_name(name), 126 shm_server::role_name(name), S, in_obj_max_count, 127 out_obj_max_count) {} 128 129 void wait_until_client_start() { 130 internal::shm_session_server *ss = 131 (internal::shm_session_server *)internal::shm_service_base::session(); 132 ss->wait_until_client_start(); 133 } 134 }; 135 136 template <size_t S> 137 class shm_service_client : public internal::shm_service_base { 138 public: 139 shm_service_client(const std::string &name, size_t in_obj_max_count, 140 size_t out_obj_max_count) 141 : internal::shm_service_base( 142 role_client, name, 143 internal::shm_other_side_role<shm_client>::type::role_name(name), 144 shm_client::role_name(name), S, in_obj_max_count, 145 out_obj_max_count) {} 146 }; 147 148 template <size_t S> class shm_service_util : public internal::shm_service_base { 149 public: 150 shm_service_util(const std::string &name, size_t in_obj_max_count, 151 size_t out_obj_max_count) 152 : internal::shm_service_base( 153 role_util, name, 154 internal::shm_other_side_role<shm_server>::type::role_name(name), 155 shm_server::role_name(name), S, in_obj_max_count, 156 out_obj_max_count) {} 157 }; 158 } 159 }