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  }