#include <functional>
#include <type_traits>
#include <utility>
#include <memory>
template <std::size_t... Is>
struct indices {};
template <std::size_t N, std::size_t... Is>
struct build_indices
: build_indices<N - 1, N - 1, Is...> {};
template <std::size_t... Is>
struct build_indices<0, Is...> : indices<Is...>{};
template<int I> struct placeholder{};
namespace std{
template<int I>
struct is_placeholder< ::placeholder<I>> : std::integral_constant<int, I>{};
} // std::
namespace detail{
template<std::size_t... Is, class F, class... Args>
auto easy_bind(indices<Is...>, F const& f, Args&&... args)
-> decltype(std::bind(f, std::forward<Args>(args)..., placeholder<1 + Is>{}...))
{
return std::bind(f, std::forward<Args>(args)..., placeholder<1 + Is>{}...);
}
} // detail::
template<class F, class... FArgs, class... Args>
auto easy_bind(F const& f, Args&&... args)
-> decltype(detail::easy_bind(build_indices<sizeof...(FArgs)-sizeof...(Args)>{}, f, std::forward<Args>(args)...))
{
return detail::easy_bind(build_indices<sizeof...(FArgs)-sizeof...(Args)>{}, f, std::forward<Args>(args)...);
}
/*
* Event
*
* Event()
* ~Event()
* // don't destroy an event while executing it
*
* void clear()
* void reverse()
*
* Event::id reg(function, args...)
* Event::id->enable = true|false;
* Event::id->unreg();
* Event::id->replace(function, args...)
*
* void exec()
* - runs all functions on Event
*/
template<typename... Params>
class Event
{
struct Node;
public:
/*
* Types
*/
typedef Node* id;
private:
/*
* Structures
*/
struct Node
{
std::function<void(Params...)> dat;
bool enable;
bool destroy;
Node* next;
Node* prev;
Event* event;
inline void unreg()
{
destroy = true;
} //unreg
template<class T, class... Args>
void replace(T&& func, Args&&... args)
{
dat = easy_bindEx<T, Params..., Args...>(func, args...);
} //replace
}; //Node
/*
* Fields
*/
Node* first;
Node* last;
bool reversed;
void unreg(id eventId)
{
if (eventId->next)
{
eventId->next->prev = eventId->prev;
} //if
else
{
last = eventId->prev;
} //else
if (eventId->prev)
{
eventId->prev->next = eventId->next;
}
else
{
first = eventId->next;
} //else
} //unreg
public:
/*
* Constructors
*/
Event()
{
first = NULL;
last = NULL;
reversed = false;
} //Event
~Event()
{
Node* next;
while (first)
{
next = first->next;
delete first;
first = next;
} //while
last = NULL;
} //~Event
/*
* Data Manipulation Operations
*/
template<class T, class... Args>
id reg(T&& func, Args&&... args)
{
Node* node = new Node();
node->dat = easy_bindEx<T, Params..., Args...>(func, args...);
node->event = this;
node->enable = true;
node->destroy = false;
if (reversed)
{
node->prev = NULL;
node->next = first;
if (first == NULL)
{
last = node;
} //if
else
{
first->prev = node;
} //else
first = node;
} //if
else
{
node->next = NULL;
node->prev = last;
if (last == NULL)
{
first = node;
} //if
else
{
last->next = node;
} //else
last = node;
} //else
return node;
} //reg
/*
template<class... P, class... Args>
id regEvent(Event<P...>& event, Args&&... args)
{
easy_bind(std::function<void(Event<P...>&, P...)>([](Event<P...>& event, Args&&... args, Params&&... params) { event.exec(forward<Args>(args)..., forward<Params>(params)...);}), event, args...);
return NULL;
//return reg(easy_bind(std::function<void(Event<P...>&, P...)>([](Event<P...>& event, Args&&... args, Params&&... params) { event.exec(forward<Args>(args)..., forward<Params>(params)...);}), event, args...));
} //regEvent
*/
void clear()
{
for (Node* node = first; node; node = node->next)
{
node->unreg();
} //for
} //clear
/*
* Structure Manipulation Operations
*
*/
void reverse()
{
if (first)
{
Node* node = first;
Node* next = node->next;
while (next)
{
node->next = node->prev;
node->prev = next;
node = next;
next = node->next;
} //while
last->next = last->prev;
last->prev = next;
node = last;
last = first;
first = node;
reversed = !reversed;
} //if
} //reverse
/*
* Execution Operations
*/
void exec(Params&&... args)
{
Node* node = first;
Node* next;
while (node)
{
next = node->next;
if (node->destroy)
{
unreg(node);
delete node;
} //if
else if (node->enable)
{
node->dat(args...);
} //else if
node = next;
} //while
} //exec
}; //Event
template<>
class Event<void>
{
struct Node;
public:
/*
* Types
*/
typedef Node* id;
private:
/*
* Structures
*/
struct Node
{
std::function<void()> dat;
bool enable;
bool destroy;
Node* next;
Node* prev;
Event* event;
inline void unreg()
{
destroy = true;
} //unreg
template<class T, class... Args>
void replace(T&& func, Args&&... args)
{
dat = easy_bindEx<T, Args...>(func, args...);
} //replace
}; //Node
/*
* Fields
*/
Node* first;
Node* last;
bool reversed;
void unreg(id eventId)
{
if (eventId->next)
{
eventId->next->prev = eventId->prev;
} //if
else
{
last = eventId->prev;
} //else
if (eventId->prev)
{
eventId->prev->next = eventId->next;
}
else
{
first = eventId->next;
} //else
} //unreg
public:
/*
* Constructors
*/
Event()
{
first = NULL;
last = NULL;
reversed = false;
} //Event
~Event()
{
Node* next;
while (first)
{
next = first->next;
delete first;
first = next;
} //while
last = NULL;
} //~Event
/*
* Data Manipulation Operations
*/
template<class T, class... Args>
id reg(T&& func, Args&&... args)
{
Node* node = new Node();
node->dat = easy_bindEx<T, Args...>(func, args...);
node->event = this;
node->enable = true;
node->destroy = false;
if (reversed)
{
node->prev = NULL;
node->next = first;
if (first == NULL)
{
last = node;
} //if
else
{
first->prev = node;
} //else
first = node;
} //if
else
{
node->next = NULL;
node->prev = last;
if (last == NULL)
{
first = node;
} //if
else
{
last->next = node;
} //else
last = node;
} //else
return node;
} //reg
void clear()
{
for (Node* node = first; node; node = node->next)
{
node->unreg();
} //for
} //clear
/*
* Structure Manipulation Operations
*
*/
void reverse()
{
if (first)
{
Node* node = first;
Node* next = node->next;
while (next)
{
node->next = node->prev;
node->prev = next;
node = next;
next = node->next;
} //while
last->next = last->prev;
last->prev = next;
node = last;
last = first;
first = node;
reversed = !reversed;
} //if
} //reverse
/*
* Execution Operations
*/
void exec()
{
Node* node = first;
Node* next;
while (node)
{
next = node->next;
if (node->destroy)
{
unreg(node);
delete node;
} //if
else if (node->enable)
{
node->dat();
} //else if
node = next;
} //while
} //exec
}; //Event
#include <functional>
#include <vector>
void myF1(std::vector<int>& v, int, int)
{
v.push_back(v.back() + 1);
}
void myF2(std::vector<int>& v, int, int)
{
v.push_back(v.back() + 1);
}
void myF3(std::vector<int>& v, int, int)
{
v.push_back(v.back() + 1);
}
void myF4(std::vector<int>& v, int, int)
{
v.push_back(v.back() + 1);
}
void myF5(std::vector<int>& v, int, int)
{
v.push_back(v.back() + 1);
}
void myF6(std::vector<int>& v, int, int)
{
v.push_back(v.back() + 1);
}
void myF7(std::vector<int>& v, int, int)
{
v.push_back(v.back() + 1);
}
void myF8(std::vector<int>& v, int, int)
{
v.push_back(v.back() + 1);
}
void myF9(std::vector<int>& v, int, int)
{
v.push_back(v.back() + 1);
}
void myF10(std::vector<int>& v, int, int)
{
v.push_back(v.back() + 1);
}
#include <ctime>
#include <iostream>
#include <chrono>
#include <random>
int main()
{
Event<std::vector<int>&, int, int> ev;
auto ev1P = ev.reg(myF1);
auto ev2P = ev.reg(myF2);
auto ev3P = ev.reg(myF3);
auto ev4P = ev.reg(myF4);
auto ev5P = ev.reg(myF5);
auto ev6P = ev.reg(myF6);
auto ev7P = ev.reg(myF7);
auto ev8P = ev.reg(myF8);
auto ev9P = ev.reg(myF9);
auto ev10P = ev.reg(myF10);
std::vector<int> v;
v.reserve(10000000);
std::vector<int> rNums;
rNums.reserve(v.capacity());
std::mt19937 mTwist(std::chrono::high_resolution_clock::now().time_since_epoch().count());
std::uniform_int_distribution<> uDist;
for(int i = 0; i < v.capacity(); ++i)
{
rNums.push_back(uDist(mTwist));
}
auto now = std::chrono::high_resolution_clock::now();
for(int i = 0; i < 100000; ++i)
{
ev.exec(v, rNums[i], rNums[i]);
}
auto after = std::chrono::high_resolution_clock::now();
std::cout << "calling 100,000 fires took " <<
std::chrono::duration_cast<std::chrono::microseconds>(after - now).count() << " milliseconds\n";
std::cout << "size: " << v.size() << "\n";
std::cin.get();
}