- Joined
- Jul 10, 2007
- Messages
- 6,306
Code:
#pragma once
#include <vector>
#include <functional>
#include <stack>
#include <mutex>
#include <atomic>
template<typename... Params>
class Event
{
struct Callback
{
int id;
int type;
void(*callback)(Params...);
Event* event;
std::function<void(Params...)> callbackEx;
}; //Callback
std::vector<Callback> callback;
std::stack<int> recycler;
std::mutex key;
int id;
std::atomic<bool> reversed;
int getId()
{
int id = 0;
if (recycler.empty())
{
id = ++this->id;
} //if
else
{
id = recycler.top();
recycler.pop();
} //else
return id;
} //getId
void recycle(const int& id)
{
recycler.push(id);
} //recycle
public:
Event()
{
id = 0;
reversed = false;
} //Event
inline void reverse()
{
reversed = !reversed;
} //reverse
int add(std::function<void(Params...)> f)
{
//breaks
key.lock();
int id = getId();
this->callback.push_back({ id, 1, NULL, NULL, f });
key.unlock();
return id;
} //add
int add(void(*f)(Params...))
{
key.lock();
int id = getId();
callback.push_back({ id, 2, f });
key.unlock();
return id;
} //add
int add(Event& event)
{
key.lock();
int id = getId();
callback.push_back({ id, 3, NULL, &event });
key.unlock();
return id;
} //add
int add(Event* event)
{
key.lock();
int id = getId();
callback.push_back({ id, 3, NULL, event });
key.unlock();
return id;
} //add
Event& operator-=(int id)
{
key.lock();
auto i = callback.begin();
while (i != callback.end())
{
if (i->id == id)
{
callback.erase(i);
recycle(id);
break;
} //if
++i;
} //for
key.unlock();
return *this;
} //-=
Event& operator=(Event& other)
{
return other;
} //-=
void operator()(Params... params)
{
int id;
if (reversed)
{
key.lock();
int i = callback.size() - 1;
key.unlock();
for (; i >= 0; --i)
{
key.lock();
Callback& node = callback[i];
key.unlock();
id = node.id;
switch (node.type)
{
case 1:
node.callbackEx(params...);
break;
case 2:
node.callback(params...);
break;
case 3:
(*(node.event))(params...);
break;
default:
break;
} //switch
} //for
} //if
else
{
key.lock();
for (int i = 0; i < callback.size(); ++i)
{
Callback& node = callback[i];
key.unlock();
id = node.id;
switch (node.type)
{
case 1:
node.callbackEx(params...);
break;
case 2:
node.callback(params...);
break;
case 3:
(*(node.event))(params...);
break;
default:
break;
} //switch
key.lock();
if (i < callback.size() && id != node.id)
{
--i;
} //if
} //for
key.unlock();
} //else
} //()
void clear()
{
recycler.empty();
id = 0;
callback.empty();
} //clear
}; //Event
template<>
class Event < void >
{
struct Callback
{
int id;
int type;
void(*callback)();
Event* event;
std::function<void()> callbackEx;
}; //Callback
std::vector<Callback> callback;
std::stack<int> recycler;
int id;
std::mutex key;
std::atomic<bool> reversed;
int getId()
{
if (recycler.empty())
{
return ++id;
} //if
int id = recycler.top();
recycler.pop();
return id;
} //getId
void recycle(const int& id)
{
recycler.push(id);
} //recycle
public:
Event()
{
id = 0;
reversed = false;
} //Event
inline void reverse()
{
reversed = !reversed;
} //reverse
int add(std::function<void()> f)
{
key.lock();
int id = getId();
this->callback.push_back({ id, 1, NULL, NULL, f });
key.unlock();
return id;
} //add
int add(void(*f)())
{
key.lock();
int id = getId();
callback.push_back({ id, 2, f });
key.unlock();
return id;
} //add
int add(Event& event)
{
key.lock();
int id = getId();
callback.push_back({ id, 3, NULL, &event });
key.unlock();
return id;
} //add
int add(Event* event)
{
key.lock();
int id = getId();
callback.push_back({ id, 3, NULL, event });
key.unlock();
key.unlock();
return id;
} //add
Event& operator-=(int id)
{
key.lock();
auto i = callback.begin();
while (i != callback.end())
{
if (i->id == id)
{
callback.erase(i);
recycle(id);
break;
} //if
++i;
} //for
key.unlock();
return *this;
} //-=
Event& operator=(Event& other)
{
return other;
} //-=
void operator()()
{
int id;
if (reversed)
{
key.lock();
int i = callback.size() - 1;
key.unlock();
for (; i >= 0; --i)
{
key.lock();
Callback& node = callback[i];
key.unlock();
id = node.id;
switch (node.type)
{
case 1:
node.callbackEx();
break;
case 2:
node.callback();
break;
case 3:
(*(node.event))();
break;
default:
break;
} //switch
} //for
} //if
else
{
key.lock();
for (int i = 0; i < callback.size(); ++i)
{
Callback& node = callback[i];
key.unlock();
id = node.id;
switch (node.type)
{
case 1:
node.callbackEx();
break;
case 2:
node.callback();
break;
case 3:
(*(node.event))();
break;
default:
break;
} //switch
key.lock();
if (i < callback.size() && id != node.id)
{
--i;
} //if
} //for
key.unlock();
} //else
} //()
void clear()
{
recycler.empty();
id = 0;
callback.empty();
} //clear
}; //Event
Code:
#include <iostream>
#include "event.h"
using namespace std;
void test();
int main(int argc, char** argv)
{
test();
return 0;
} //main
void meh(const int& a, const int& b)
{
cout << "test meh" << a << b << endl;
} //meh
void moo(const int& a, const int& b)
{
cout << "test moo" << a << b << endl;
} //meh
struct Test
{
void test(const int& a, const int& b)
{
cout << "test test" << a << b << endl;
}
}; //Test
void ehh()
{
cout << "ehhh" << endl;
}
void test()
{
Event<const int&, const int&> event;
Test tester;
//event.reverse();
event.add([&tester, &event](const int& a, const int& b) { tester.test(a, b); event -= 1; });
event.add([&tester, &event](const int& a, const int& b) { tester.test(a, b); event -= 2; });
event.add(meh);
event.add([&tester, &event](const int& a, const int& b) { tester.test(a, b); event -= 4; });
event.add(meh);
event.add([&tester, &event](const int& a, const int& b) { tester.test(a, b); event -= 6; });
event.add(meh);
event.add(meh);
event.add([&tester, &event](const int& a, const int& b) { tester.test(a, b); event -= 9; });
event.add([&tester, &event](const int& a, const int& b) { tester.test(a, b); event -= 10; });
event(1, 2);
cout << "--------------------------" << endl;
event(1, 2);
} //test
Last edited: