Created
July 20, 2011 14:43
-
-
Save r2p2/1095090 to your computer and use it in GitHub Desktop.
Xer Signalklasse
This file contains 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 <iostream> | |
#include <vector> | |
struct CallbackNoArg | |
{ | |
}; | |
class CallbackBase | |
{ | |
public: | |
virtual void operator()(void *arg0 = 0, | |
void *arg1 = 0, | |
void *arg2 = 0) = 0; | |
}; | |
template <class T, class Arg0 = CallbackNoArg, | |
class Arg1 = CallbackNoArg, | |
class Arg2 = CallbackNoArg> | |
class Callback : public CallbackBase | |
{ | |
public: | |
Callback(T &object, void (T::*method0)()) | |
:CallbackBase() | |
,m_object(object) | |
,m_method0(method0) | |
,m_argc(0) | |
{ | |
} | |
Callback(T &object, void (T::*method1)(Arg0)) | |
:m_object(object) | |
,m_method1(method1) | |
,m_argc(1) | |
{ | |
} | |
Callback(T &object, void (T::*method2)(Arg0, Arg1)) | |
:m_object(object) | |
,m_method2(method2) | |
,m_argc(2) | |
{ | |
} | |
Callback(T &object, void (T::*method3)(Arg0, Arg1, Arg2)) | |
:m_object(object) | |
,m_method3(method3) | |
,m_argc(3) | |
{ | |
} | |
virtual void operator()(void *arg0 = 0, | |
void *arg1 = 0, | |
void *arg2 = 0) | |
{ | |
switch(m_argc) | |
{ | |
case 0: | |
(m_object.*m_method0)(); | |
break; | |
case 1: | |
(m_object.*m_method1)(*reinterpret_cast<Arg0*>(arg0)); | |
break; | |
case 2: | |
(m_object.*m_method2)(*reinterpret_cast<Arg0*>(arg0), | |
*reinterpret_cast<Arg1*>(arg1)); | |
break; | |
case 3: | |
(m_object.*m_method3)(*reinterpret_cast<Arg0*>(arg0), | |
*reinterpret_cast<Arg1*>(arg1), | |
*reinterpret_cast<Arg2*>(arg2)); | |
break; | |
} | |
} | |
private: | |
T &m_object; | |
void (T::*m_method0)(); | |
void (T::*m_method1)(Arg0); | |
void (T::*m_method2)(Arg0, Arg1); | |
void (T::*m_method3)(Arg0, Arg1, Arg2); | |
unsigned int m_argc; | |
}; | |
template <class Arg0 = CallbackNoArg, | |
class Arg1 = CallbackNoArg, | |
class Arg2 = CallbackNoArg> | |
class Signal | |
{ | |
struct data_t | |
{ | |
CallbackBase* cb; | |
bool dynamic; | |
}; | |
public: | |
Signal() | |
:m_callbacks() | |
{ | |
} | |
~Signal() | |
{ | |
unsigned int size = m_callbacks.size(); | |
for(unsigned int i = 0; i < size; ++i) | |
{ | |
delete m_callbacks[i]; | |
} | |
} | |
template<class T> | |
void register_callback(T &object, void (T::*method)()) | |
{ | |
m_callbacks.push_back(new Callback<T>(object, method)); | |
} | |
template<class T> | |
void register_callback(T &object, void (T::*method)(Arg0)) | |
{ | |
m_callbacks.push_back(new Callback<T, Arg0>(object, method)); | |
} | |
template<class T> | |
void register_callback(T &object, void (T::*method)(Arg0, Arg1)) | |
{ | |
m_callbacks.push_back(new Callback<T, Arg0, Arg1>(object, method)); | |
} | |
template<class T> | |
void register_callback(T &object, void (T::*method)(Arg0, Arg1, Arg2)) | |
{ | |
m_callbacks.push_back(new Callback<T, Arg0, Arg1, Arg2>(object, method)); | |
} | |
// ACHTUNG: hier werden die Argumente nicht als Referenz übergeben. Geht das irgenwie sinnvoll? | |
// ok, man könnte emit_signal auch überladen | |
void emit_signal(Arg0 arg0 = CallbackNoArg(), Arg1 arg1 = CallbackNoArg(), Arg2 arg2 = CallbackNoArg()) | |
{ | |
unsigned int size = m_callbacks.size(); | |
for(unsigned int i = 0; i < size; ++i) | |
{ | |
(*(m_callbacks[i]))(reinterpret_cast<void*>(&arg0), reinterpret_cast<void*>(&arg1), reinterpret_cast<void*>(&arg2)); | |
} | |
} | |
private: | |
Signal(Signal const &orig); | |
std::vector<CallbackBase*> m_callbacks; | |
}; | |
class Timer | |
{ | |
public: | |
Timer() | |
:m_pcb(0) | |
{ | |
} | |
template<class T> | |
void registerCallback(T &cb) | |
{ | |
m_pcb = &reinterpret_cast<CallbackBase&>(cb); | |
} | |
void useCallback(int x) | |
{ | |
(*m_pcb)(reinterpret_cast<void*>(&x)); | |
} | |
void useCallback(double a, double b) | |
{ | |
(*m_pcb)(reinterpret_cast<void*>(&a),reinterpret_cast<void*>(&b)); | |
} | |
private: | |
CallbackBase *m_pcb; | |
}; | |
class Example | |
{ | |
public: | |
void foo() | |
{ | |
std::cout << "hello world" << std::endl; | |
} | |
void inc(int arg0) | |
{ | |
std::cout << "inc: " << arg0+1 << std::endl; | |
} | |
void add_two(int arg0) | |
{ | |
std::cout << "add 2: " << arg0+2 << std::endl; | |
} | |
void call2(double a, double b) | |
{ | |
std::cout << "hi: " << a/b << std::endl; | |
} | |
}; | |
int main() | |
{ | |
Example e; | |
Signal<int> s; | |
s.register_callback(e, &Example::inc); | |
s.register_callback(e, &Example::add_two); | |
s.emit_signal(5); | |
Signal<> s2; | |
s2.register_callback(e, &Example::foo); | |
s2.emit_signal(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment