github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/core/command.h (about)

     1  // Copyright (C) 2017 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  
    21  #pragma once
    22  #include "common/common.h"
    23  #include "util/singleton.h"
    24  
    25  namespace neb {
    26  namespace core {
    27  typedef uint64_t command_type_t;
    28  
    29  struct base_command {
    30    virtual ~base_command() = default;
    31  }; // end class base_command
    32  
    33  struct exit_command : public base_command {
    34    constexpr static command_type_t command_type = 1;
    35  }; // end class exit_command
    36  
    37  class command_queue : public util::singleton<command_queue> {
    38  public:
    39    template <typename CT> void send_command(const std::shared_ptr<CT> &cmd) {
    40      std::lock_guard<std::mutex> _l(m_mutex);
    41      for (handlers_t::iterator it = m_handlers.begin(); it != m_handlers.end();
    42           ++it) {
    43        if (CT::command_type == it->m_command) {
    44          it->m_handler(cmd);
    45        }
    46      }
    47    }
    48  
    49    template <typename CT>
    50    void
    51    listen_command(void *instance,
    52                   const std::function<void(const std::shared_ptr<CT> &)> &func) {
    53      std::lock_guard<std::mutex> _l(m_mutex);
    54      m_handlers.push_back(
    55          command_entity_t(CT::command_type, instance,
    56                           [func](const std::shared_ptr<base_command> &cmd) {
    57                             func(std::static_pointer_cast<CT>(cmd));
    58                           }));
    59    }
    60  
    61    template <typename CT> void unlisten_command(void *instance) {
    62      //! Notice that we may have multiple handlers for the same instance,
    63      // and we need remove them all.
    64      std::lock_guard<std::mutex> _l(m_mutex);
    65      for (handlers_t::reverse_iterator it = m_handlers.rbegin();
    66           it != m_handlers.rend(); ++it) {
    67        if (it->m_command == CT::command_type && it->m_instance == instance) {
    68          m_handlers.erase(it.base() - 1);
    69        }
    70      }
    71    }
    72    inline void unlisten_command(void *instance) {
    73      //! Notice that we may have multiple handlers for the same instance,
    74      // and we need remove them all.
    75      std::lock_guard<std::mutex> _l(m_mutex);
    76      for (handlers_t::reverse_iterator it = m_handlers.rbegin();
    77           it != m_handlers.rend(); ++it) {
    78        if (it->m_instance == instance) {
    79          m_handlers.erase(it.base() - 1);
    80        }
    81      }
    82    }
    83  
    84  protected:
    85    typedef struct command_entity {
    86      inline command_entity(
    87          command_type_t cmd, void *instance,
    88          const std::function<void(const std::shared_ptr<base_command> &)> &f)
    89          : m_command(cmd), m_instance(instance), m_handler(f) {}
    90      command_type_t m_command;
    91      void *m_instance;
    92      std::function<void(const std::shared_ptr<base_command> &)> m_handler;
    93    } command_entity_t;
    94    typedef std::vector<command_entity_t> handlers_t;
    95    handlers_t m_handlers;
    96    std::mutex m_mutex;
    97  }; // end class command_queue
    98  } // end namespace core
    99  }