github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/common/ipc/shm_service.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_service.h" 21 22 namespace neb { 23 namespace ipc { 24 namespace internal { 25 26 shm_service_base::shm_service_base(shm_role role, const std::string &shm_name, 27 const std::string &shm_in_name, 28 const std::string &shm_out_name, 29 size_t mem_size, size_t shm_in_capacity, 30 size_t shm_out_capacity) 31 : m_role(role), m_mem_size(mem_size), m_shm_in_capacity(shm_in_capacity), 32 m_shm_out_capacity(shm_out_capacity), m_shm_name(shm_name), 33 m_shm_in_name(shm_in_name), m_shm_out_name(shm_out_name) {} 34 35 shm_service_base::~shm_service_base() { 36 delete m_in_buffer; 37 delete m_out_buffer; 38 39 delete m_shmem; 40 m_session->bookkeeper()->release(m_shm_name, [this]() { 41 boost::interprocess::shared_memory_object::remove(m_shm_name.c_str()); 42 }); 43 } 44 45 void shm_service_base::reset() { 46 boost::interprocess::shared_memory_object::remove(m_shm_name.c_str()); 47 init_local_interprocess_var(); 48 m_in_buffer->reset(); 49 m_out_buffer->reset(); 50 m_session->reset(); 51 } 52 53 void shm_service_base::run() { thread_func(); } 54 55 void shm_service_base::init_local_interprocess_var() { 56 if (m_role == role_util) { 57 m_session = std::unique_ptr<shm_session_base>( 58 new shm_session_util(m_shm_name + ".session")); 59 } 60 if (m_role == role_server) { 61 m_session = std::unique_ptr<shm_session_base>( 62 new shm_session_server(m_shm_name + ".session")); 63 } 64 if (m_role == role_client) { 65 m_session = std::unique_ptr<shm_session_base>( 66 new shm_session_client(m_shm_name + ".session")); 67 } 68 69 m_session->bookkeeper()->acquire(m_shm_name, [this]() { 70 m_shmem = new boost::interprocess::managed_shared_memory( 71 boost::interprocess::open_or_create, m_shm_name.c_str(), m_mem_size); 72 }); 73 m_char_allocator = 74 std::make_unique<char_allocator_t>(m_shmem->get_segment_manager()); 75 m_default_allocator = 76 std::make_unique<default_allocator_t>(m_shmem->get_segment_manager()); 77 78 m_in_buffer = new shm_queue(m_shm_in_name.c_str(), m_session.get(), m_shmem, 79 m_shm_in_capacity); 80 m_out_buffer = new shm_queue(m_shm_out_name.c_str(), m_session.get(), m_shmem, 81 m_shm_out_capacity); 82 } 83 84 void shm_service_base::init_local_env() { 85 init_local_interprocess_var(); 86 87 neb::core::command_queue::instance().listen_command<neb::core::exit_command>( 88 this, [this](const std::shared_ptr<neb::core::exit_command> &) { 89 m_exit_flag = true; 90 m_op_queue->wake_up_if_empty(); 91 }); 92 m_op_queue = 93 std::unique_ptr<shm_service_op_queue>(new shm_service_op_queue()); 94 m_constructer = std::unique_ptr<shm_service_construct_helper>( 95 new shm_service_construct_helper(m_shmem, m_op_queue.get())); 96 m_recv_handler = std::unique_ptr<shm_service_recv_handler>( 97 new shm_service_recv_handler(m_shmem, m_op_queue.get())); 98 m_queue_watcher = std::unique_ptr<shm_queue_watcher>( 99 new shm_queue_watcher(m_in_buffer, m_op_queue.get())); 100 } 101 102 void shm_service_base::thread_func() { 103 m_queue_watcher->start(); 104 m_session->start_session(); 105 try { 106 while (!m_exit_flag) { 107 auto ret = m_op_queue->pop_front(); 108 if (ret.first) { 109 std::shared_ptr<shm_service_op_base> &op = ret.second; 110 if (op->op_id() == shm_service_op_base::op_allocate_obj) { 111 m_constructer->handle_construct_op(op); 112 } else if (op->op_id() == shm_service_op_base::op_recv_obj) { 113 m_recv_handler->handle_recv_op(op); 114 } else if (op->op_id() == shm_service_op_base::op_push_back) { 115 shm_service_op_push_back *push_op = 116 static_cast<shm_service_op_push_back *>(op.get()); 117 m_out_buffer->push_back(push_op->m_type_id, push_op->m_pointer); 118 } else if (op->op_id() == shm_service_op_base::op_destroy) { 119 m_constructer->handle_destroy_op(op); 120 } else if (op->op_id() == shm_service_op_base::op_general) { 121 shm_service_op_general *og = (shm_service_op_general *)op.get(); 122 try { 123 og->m_func(); 124 } catch (...) { 125 LOG(ERROR) << "shm_service_base got exception when run general op"; 126 } 127 } 128 } 129 } 130 } catch (const std::exception &e) { 131 LOG(ERROR) << "shm_service_base got: " << e.what(); 132 } 133 } 134 } // namespace internal 135 } // namespace ipc 136 } // namespace neb