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