Last active
April 7, 2021 11:07
-
-
Save GTANAdam/25b1a41ff5f56efb62a9db83970fb491 to your computer and use it in GitHub Desktop.
C++14 events similar to C#, low overhead event bus with optional thread safety
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #include <vector> | |
| #ifdef THREAD_SAFE_EVENTS | |
| #include <shared_mutex> | |
| #define MUTEX std::shared_mutex rwmutex; | |
| #define RWLOCK rwmutex.lock(); | |
| #define RWUNLOCK rwmutex.unlock(); | |
| #define RLOCK rwmutex.lock_shared(); | |
| #define RUNLOCK rwmutex.unlock_shared(); | |
| #else | |
| #define MUTEX | |
| #define RWLOCK | |
| #define RWUNLOCK | |
| #define RLOCK | |
| #define RUNLOCK | |
| #endif | |
| template<class T> | |
| struct Event | |
| { | |
| typedef void (*fptr)(T); | |
| std::vector<fptr> store; | |
| MUTEX; | |
| Event() {} | |
| Event(const fptr _fn) | |
| { | |
| *this += _fn; | |
| } | |
| void operator += (const fptr _fn) | |
| { | |
| if (!_fn) return; | |
| RWLOCK | |
| store.push_back(_fn); | |
| RWUNLOCK | |
| } | |
| void operator -= (const fptr _fn) | |
| { | |
| if (!_fn) return; | |
| RWLOCK | |
| for (auto iter = store.begin(); iter != store.end(); ++iter) | |
| { | |
| if (*iter._Ptr == _fn) | |
| { | |
| store.erase(iter); | |
| break; | |
| } | |
| } | |
| RWUNLOCK | |
| } | |
| // Important: can't call this on functions that do require arguments | |
| void operator()() | |
| { | |
| RLOCK | |
| for (auto iter = store.begin(); iter != store.end(); ++iter) | |
| { | |
| static_cast<fptr>(*iter)(); | |
| } | |
| RUNLOCK | |
| } | |
| // Important: can't call this on functions that do not require arguments | |
| template<typename T> | |
| void operator()(T data) | |
| { | |
| RLOCK | |
| for (auto iter = store.begin(); iter != store.end(); ++iter) | |
| { | |
| static_cast<fptr>(*iter)(data); | |
| } | |
| RUNLOCK | |
| } | |
| }; | |
| // 0 overhead, in stack, stores only 1 pointer | |
| struct EventStack | |
| { | |
| typedef void (*fptr)(); | |
| fptr fn; | |
| EventStack() {} | |
| EventStack(const fptr _fn) | |
| { | |
| fn = _fn; | |
| } | |
| void operator += (const fptr _fn) | |
| { | |
| if (!_fn) return; | |
| fn = _fn; | |
| } | |
| void operator -= (const fptr _fn) | |
| { | |
| if (!_fn) return; | |
| fn = [] {}; | |
| } | |
| void operator()() | |
| { | |
| fn(); | |
| } | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio> | |
| // #define THREAD_SAFE_EVENTS | |
| #include "eventbus.h" | |
| void Hello1() | |
| { | |
| printf("HELLO!\n"); | |
| } | |
| void Hello2(const char* str) | |
| { | |
| printf("HELLO %s!\n", str); | |
| } | |
| int main() | |
| { | |
| Event<void> event1; | |
| event1 += Hello1; | |
| event1(); | |
| // Output: HELLO! | |
| Event<const char*> event2; | |
| event2 += Hello2; | |
| event2("STRANGER"); | |
| // Output: HELLO STRANGER! | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment