├── .gitignore ├── tests ├── CMakeLists.txt └── src │ └── main.cpp ├── README.md ├── LICENSE ├── CMakeLists.txt ├── .travis.yml ├── include ├── safe_event ├── event.h ├── typed_map.h └── dispatcher.h └── src └── dispatcher.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | # cmake 31 | build -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories (${SAFE_EVENT_INC}) 2 | 3 | link_directories (${SAFE_EVENT_LIB}) 4 | 5 | project (event_tests CXX) 6 | 7 | file (GLOB headers "*.h") 8 | file (GLOB sources "*.cpp") 9 | 10 | set (DIRS "src") 11 | 12 | foreach (dir ${DIRS}) 13 | file (GLOB h_${dir} "${dir}/*.h") 14 | file (GLOB s_${dir} "${dir}/*.cpp") 15 | source_group (${dir} FILES ${s_${dir}} ${h_${dir}}) 16 | set (sources ${sources} ${s_${dir}}) 17 | set (header ${headers} ${h_${dir}}) 18 | endforeach () 19 | 20 | add_executable (event_tests ${sources}) 21 | 22 | target_link_libraries (event_tests safe_event) 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # safe_event 2 | C++ 11/14 type safe light event system 3 | 4 | ## A simple example 5 | ```C++ 6 | #include 7 | #include 8 | 9 | struct hello_event { 10 | void say_hello() 11 | { std::cout << "hello world !" << std::endl; } 12 | }; 13 | 14 | int 15 | main() { 16 | se::dispatcher ev_disp; 17 | 18 | // add the hello_event struct to the available events 19 | ev_disp.add_event(); 20 | 21 | // listen hello_event 22 | ev_disp.listen(std::function([](const hello_event& ev) { 23 | std::cout << "This is a real hello_event !" << std::endl;; 24 | })); 25 | 26 | // listen any event 27 | ev_disp.listen_any([](const se::any_event& ev) { 28 | // make dynamic test to check the event type 29 | if (se::is(ev)) { 30 | std::cout << "any_event is an hello_event" << std::endl; 31 | auto real_ev = se::into(ev); 32 | real_ev.say_hello(); 33 | } 34 | }); 35 | 36 | // dispatch an event 37 | ev_disp.trigger(hello_event()); 38 | } 39 | ``` -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Jeremy Letang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # min config 2 | cmake_minimum_required (VERSION 2.8.1) 3 | 4 | if(POLICY CMP0042) 5 | cmake_policy(SET CMP0042 NEW) 6 | endif() 7 | 8 | project (safe_event CXX) 9 | 10 | #include paths 11 | set (SAFE_EVENT_INC ${CMAKE_SOURCE_DIR}/include) 12 | 13 | # lib paths 14 | set (SAFE_EVENT_LIB ${CMAKE_BINARY_DIR}) 15 | 16 | include_directories (${SAFE_EVENT_INC}) 17 | 18 | file (GLOB headers "*.h") 19 | file (GLOB sources "*.c") 20 | 21 | set (DIRS "src" "include") 22 | 23 | foreach (dir ${DIRS}) 24 | file (GLOB h_${dir} "${dir}/*.h") 25 | file (GLOB s_${dir} "${dir}/*.cpp") 26 | source_group (${dir} FILES ${s_${dir}} ${h_${dir}}) 27 | set (sources ${sources} ${s_${dir}}) 28 | set (header ${headers} ${h_${dir}}) 29 | endforeach () 30 | 31 | if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") 32 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y") 33 | elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") 34 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++1y") 35 | endif() 36 | 37 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") 38 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra") 39 | 40 | add_library (safe_event SHARED ${sources}) 41 | add_subdirectory(tests) -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | compiler: 3 | # - clang 4 | - gcc 5 | before_install: 6 | - if [ "$CXX" == "g++" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi 7 | - sudo apt-get update -qq 8 | install: 9 | - if [ "$CXX" == "g++" ]; then sudo apt-get install -qq g++-4.9; fi 10 | - if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi 11 | - if [ "$CXX" == "clang++" ]; then cwd=$(pwd); fi 12 | - if [ "$CXX" == "clang++" ]; then svn co --quiet http://llvm.org/svn/llvm-project/libcxx/trunk@201601 libcxx; fi 13 | - if [ "$CXX" == "clang++" ]; then cd libcxx/lib && bash buildit; fi 14 | - if [ "$CXX" == "clang++" ]; then sudo cp ./libc++.so.1.0 /usr/lib/; fi 15 | - if [ "$CXX" == "clang++" ]; then sudo mkdir /usr/include/c++/v1; fi 16 | - if [ "$CXX" == "clang++" ]; then cd .. && sudo cp -r include/* /usr/include/c++/v1/; fi 17 | - if [ "$CXX" == "clang++" ]; then cd /usr/lib && sudo ln -sf libc++.so.1.0 libc++.so; fi 18 | - if [ "$CXX" == "clang++" ]; then sudo ln -sf libc++.so.1.0 libc++.so.1 && cd $cwd; fi 19 | - gcc --version 20 | - g++ --version 21 | - clang --version 22 | before_script: 23 | - cmake --version 24 | - mkdir build 25 | - cd build 26 | script: 27 | - cmake .. 28 | - make -------------------------------------------------------------------------------- /include/safe_event: -------------------------------------------------------------------------------- 1 | // -*- C -*- 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2015 Jeremy Letang 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | #ifndef SAFE_EVENT 25 | #define SAFE_EVENT 26 | 27 | #include "event.h" 28 | #include "typed_map.h" 29 | #include "dispatcher.h" 30 | 31 | #endif -------------------------------------------------------------------------------- /src/dispatcher.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2015 Jeremy Letang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include "dispatcher.h" 24 | 25 | namespace se { 26 | 27 | dispatcher::dispatcher() {} 28 | 29 | dispatcher::~dispatcher() {} 30 | 31 | void 32 | dispatcher::cleanup() 33 | { this->all_events_listeners.clear(); } 34 | 35 | } -------------------------------------------------------------------------------- /tests/src/main.cpp: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2015 Jeremy Letang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #include 24 | #include 25 | 26 | struct hello_event { 27 | void say_hello() 28 | { std::cout << "hello world !" << std::endl; } 29 | }; 30 | 31 | int 32 | main() { 33 | se::dispatcher ev_disp; 34 | 35 | // add the hello_event struct to the available events 36 | ev_disp.add_event(); 37 | 38 | // listen hello_event 39 | ev_disp.listen(std::function([](const hello_event&) { 40 | std::cout << "This is a real hello_event !" << std::endl;; 41 | })); 42 | 43 | // listen any event 44 | ev_disp.listen_any([](const se::any_event& ev) { 45 | // make dynamic test to check the event type 46 | if (se::is(ev)) { 47 | std::cout << "any_event is an hello_event" << std::endl; 48 | auto real_ev = se::into(ev); 49 | real_ev.say_hello(); 50 | } 51 | }); 52 | 53 | // dispatch an event 54 | ev_disp.trigger(hello_event()); 55 | } -------------------------------------------------------------------------------- /include/event.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2015 Jeremy Letang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #ifndef SE_EVENT 24 | #define SE_EVENT 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | namespace se { 31 | 32 | struct base_any { 33 | 34 | virtual ~base_any() {} 35 | virtual const std::type_info& get_typeinfo() =0; 36 | 37 | }; 38 | 39 | template 40 | struct real_any: public base_any { 41 | 42 | private: 43 | 44 | const T &val; 45 | const std::type_info& self; 46 | 47 | public: 48 | 49 | real_any(const T &val) 50 | : val(val), self(typeid(T)) 51 | {} 52 | 53 | const std::type_info& get_typeinfo() 54 | { return self; }; 55 | 56 | const T& get() 57 | { return this->val; } 58 | 59 | }; 60 | 61 | struct any_event { 62 | 63 | private: 64 | 65 | std::unique_ptr base; 66 | 67 | public: 68 | 69 | any_event() {} 70 | 71 | template any_event(const T &val) 72 | : base(std::make_unique>(val)) 73 | {} 74 | 75 | const std::type_info& get_typeinfo() 76 | { return this->base->get_typeinfo(); }; 77 | 78 | template bool is() const 79 | { return this->base->get_typeinfo() == typeid(T); } 80 | 81 | template 82 | const T& into() const { 83 | if (!this->is()) { throw std::bad_cast(); } 84 | auto ptr = dynamic_cast*>(this->base.get()); 85 | if (ptr == nullptr) { throw std::bad_cast(); } 86 | return ptr->get(); 87 | } 88 | }; 89 | 90 | template 91 | const T& into(const any_event &ev) { 92 | return ev.into(); 93 | } 94 | 95 | template 96 | bool is(const any_event& ev) { 97 | return ev.is(); 98 | } 99 | 100 | } 101 | 102 | #endif -------------------------------------------------------------------------------- /include/typed_map.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2015 Jeremy Letang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #ifndef SE_TYPED_MAP 24 | #define SE_TYPED_MAP 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | namespace se { 32 | 33 | template 34 | void deleter(void* d) { 35 | delete (T*)d; 36 | } 37 | 38 | // an map encapsulation to store any type in the same map 39 | // only one instance of each type can be stored inside the map 40 | class typed_map { 41 | 42 | private: 43 | 44 | // the map, each type is referenced by it's type_index and cast to void* 45 | std::unordered_map>> map; 46 | 47 | public: 48 | 49 | ~typed_map() { 50 | for (auto &it : this->map) { 51 | it.second.second(it.second.first); 52 | } 53 | } 54 | 55 | // add a new type instance inside the map. 56 | // the first type parameter is the type of the new object to insert in the map 57 | // the second is the list of types parameters to instanciate the type 58 | // the methods parameters are the list of variable to pass to the type instanciation 59 | // return false if instanciation failed, true otherwise 60 | template 61 | bool add(A... args) { 62 | T *inst = new T(args...); 63 | 64 | if (inst == nullptr) { return false; } 65 | auto f = deleter; 66 | map.emplace(std::type_index(typeid(T)), std::make_pair(inst, f)); 67 | return true; 68 | } 69 | 70 | // get a pointer to the type T instance inside the map 71 | // return nullptr if the type is not inside the map or a pointer to the type instance 72 | template 73 | T *get() { 74 | auto it = this->map.find(std::type_index(typeid(T))); 75 | 76 | if (it == this->map.end()) { return nullptr; } 77 | return static_cast(it->second.first); 78 | } 79 | 80 | // check if an instance of T is already on the map 81 | template 82 | bool exist() 83 | { return !(this->map.find(std::type_index(typeid(T))) == this->map.end()); } 84 | 85 | template 86 | bool apply_while(std::function f, A... args) { 87 | for (auto it = this->map.begin(); it != this->map.end(); ++it) { 88 | if (f(static_cast(it->second.first, args)...) == true) { 89 | return true; 90 | } 91 | } 92 | return false; 93 | } 94 | 95 | }; 96 | 97 | } 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /include/dispatcher.h: -------------------------------------------------------------------------------- 1 | // The MIT License (MIT) 2 | // 3 | // Copyright (c) 2015 Jeremy Letang 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | #ifndef SE_DISPATCHER 24 | #define SE_DISPATCHER 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "event.h" 34 | #include "typed_map.h" 35 | 36 | namespace se { 37 | 38 | // internal event listener storage 39 | template 40 | struct event_producer { 41 | // the listeners 42 | std::vector> _listeners; 43 | 44 | // dispatch the event to the listeners 45 | void dispatch(const E &ev) { 46 | for (auto l : this->_listeners) { 47 | l(ev); 48 | } 49 | } 50 | 51 | // add a new listener to the internal vector of listener for this event 52 | void add_listener(std::function fn) { 53 | this->_listeners.push_back(fn); 54 | } 55 | 56 | // get the listeners list 57 | const std::vector> listeners() const { 58 | return this->_listeners; 59 | } 60 | }; 61 | 62 | class dispatcher { 63 | 64 | private: 65 | 66 | // list of listeners for all events 67 | std::vector> all_events_listeners; 68 | 69 | // typed_map containing the events producers 70 | // this ensure that only one producer exist for a given event 71 | se::typed_map producers; 72 | 73 | // allow us to use the event in an asynchronous way 74 | std::mutex access_mtx; 75 | 76 | public: 77 | 78 | dispatcher(); 79 | 80 | ~dispatcher(); 81 | 82 | // register an event inside the event dispatcher 83 | // this function muse be called before the first call of trigger and add_listener 84 | // for an event, otherwise the event is not known by the event_dispatcher 85 | // and register event will fail. 86 | // no parameter is needed, and the event is specified with type parameter 87 | // usage example: my_ev_dispatcher.register_event(); 88 | // an event can be registered only one time. 89 | // on success this function create a new event_producer, store it internaly 90 | // and return true, on error false is returned. 91 | template 92 | bool add_event() { 93 | std::lock_guard lock(this->access_mtx); 94 | 95 | if (this->producers.exist>()) { 96 | return false; 97 | } 98 | 99 | this->producers.add>(); 100 | return true; 101 | } 102 | 103 | // add a listener to an existing event. 104 | // the function take an std::function parameterized with the type of the 105 | // event, e.g for an event `custom_event`, the parameter of add_listener 106 | // should be of type std::function 107 | // if the event exist true true is return, false otherwise 108 | template 109 | bool listen(std::function fn) { 110 | std::lock_guard lock(this->access_mtx); 111 | 112 | if (!this->producers.exist>()) { 113 | this->add_event(); 114 | } 115 | 116 | this->producers.get>()->add_listener(fn); 117 | 118 | return true; 119 | } 120 | 121 | bool listen_any(std::function fn) { 122 | std::lock_guard lock(this->access_mtx); 123 | 124 | this->all_events_listeners.push_back(fn); 125 | 126 | return true; 127 | } 128 | 129 | // trigger a new event 130 | // the event must be previously registered with `add_event` 131 | // the function check if the event is register the event is 132 | // dispatched to the producer and true is returned, otherwise 133 | // false is returned 134 | template 135 | bool trigger(const E &ev) { 136 | std::lock_guard lock(this->access_mtx); 137 | 138 | if (!this->producers.exist>()) { 139 | return false; 140 | } 141 | 142 | // notify listener of the given event 143 | this->producers.get>()->dispatch(ev); 144 | 145 | // notify listeners of all events 146 | if (!this->all_events_listeners.empty()) { 147 | auto any_ev = any_event(ev); 148 | for (auto al : this->all_events_listeners) { 149 | al(any_ev); 150 | } 151 | } 152 | return true; 153 | } 154 | 155 | // cleanup all listeners before exit 156 | void cleanup(); 157 | 158 | }; 159 | 160 | } 161 | 162 | #endif 163 | --------------------------------------------------------------------------------