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 }