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  }