Skip to content

Instantly share code, notes, and snippets.

@GTANAdam
Last active April 7, 2021 11:07
Show Gist options
  • Select an option

  • Save GTANAdam/25b1a41ff5f56efb62a9db83970fb491 to your computer and use it in GitHub Desktop.

Select an option

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
#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();
}
};
#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