first commit
This commit is contained in:
175
include/platform/signal/signal.h
Normal file
175
include/platform/signal/signal.h
Normal file
@ -0,0 +1,175 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __SIGNAL__
|
||||
#define __SIGNAL__
|
||||
|
||||
|
||||
#include "container/nlist.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
|
||||
//
|
||||
template <typename T> class Signal
|
||||
{
|
||||
/// Base signal listener.
|
||||
struct IListener
|
||||
{
|
||||
virtual void Call(T) = 0;
|
||||
|
||||
virtual bool BelongsToInstance(void *) const = 0;
|
||||
virtual bool IsFunction(void (*)(T)) const = 0;
|
||||
|
||||
virtual ~IListener() {}
|
||||
};
|
||||
|
||||
AutoList <IListener *> listeners;
|
||||
|
||||
/// Pointer to member listener.
|
||||
template <class O, typename T1> struct InstanceListener : public IListener
|
||||
{
|
||||
O *i;
|
||||
void (O::*f)(T1);
|
||||
|
||||
void Call(T1 t) { (i->*f)(t); }
|
||||
|
||||
bool BelongsToInstance(void *p) const { return asbool(p == (void *)i); }
|
||||
bool IsFunction(void (*)(T1)) const { return false; }
|
||||
|
||||
InstanceListener(O *_i, void (O::*_f)(T1)) : i(_i), f(_f) {}
|
||||
};
|
||||
|
||||
/// Global/static function listener.
|
||||
template <typename T1> struct FunctionListener : public IListener
|
||||
{
|
||||
void (*f)(T1);
|
||||
|
||||
void Call(T1 t) { (*f)(t); }
|
||||
|
||||
bool BelongsToInstance(void *) const { return false; }
|
||||
bool IsFunction(void (*_f)(T1)) const { return f == _f; }
|
||||
|
||||
FunctionListener(void (*_f)(T1)) : f(_f) {}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/// Return the number of listener on this signal.
|
||||
uint GetListenerCount() const { return listeners.GetCount(); }
|
||||
|
||||
/// Subscribe an instance member function to call when the event is triggered.
|
||||
template <class O> void Connect(O *i, void (O::*f)(T))
|
||||
{ listeners.Add(new InstanceListener <O, T> (i, f)); }
|
||||
/// Remove the subscription of all handlers associated with a specific class instance.
|
||||
template <class O> void Disconnect(O *i)
|
||||
{
|
||||
ListForeachPtr(IListener *, l, this->listeners)
|
||||
if (l->BelongsToInstance((void *)i))
|
||||
listeners.Remove(l);
|
||||
}
|
||||
|
||||
/// Subscribe a function to call when the event is triggered.
|
||||
void Connect(void (*f)(T))
|
||||
{ listeners.Add(new FunctionListener <T> (f)); }
|
||||
/// Remove a function subscription.
|
||||
void Disconnect(void (*f)(T))
|
||||
{
|
||||
ListForeachPtr(IListener *, l, this->listeners)
|
||||
if (l->IsFunction(f))
|
||||
listeners.Remove(l);
|
||||
}
|
||||
|
||||
/// Emit the signal, notifies all listeners.
|
||||
void Emit(T t) const
|
||||
{
|
||||
ListForeachPtr(IListener *, l, listeners)
|
||||
l->Call(t);
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization for void type. Note: I gave up on factoring code => compiler vendor/extension hell.
|
||||
template <> class Signal <void>
|
||||
{
|
||||
/// Base signal listener.
|
||||
struct IListener
|
||||
{
|
||||
virtual void Call() = 0;
|
||||
|
||||
virtual bool BelongsToInstance(void *) const = 0;
|
||||
virtual bool IsFunction(void (*)()) const = 0;
|
||||
|
||||
virtual ~IListener() {}
|
||||
};
|
||||
|
||||
AutoList <IListener *> listeners;
|
||||
|
||||
/// Pointer to member listener.
|
||||
template <class O> struct InstanceListener : public IListener
|
||||
{
|
||||
O *i;
|
||||
void (O::*f)();
|
||||
|
||||
void Call() { (i->*f)(); }
|
||||
|
||||
bool BelongsToInstance(void *p) const { return asbool(p == (void *)i); }
|
||||
bool IsFunction(void (*)()) const { return false; }
|
||||
|
||||
InstanceListener(O *_i, void (O::*_f)()) : i(_i), f(_f) {}
|
||||
};
|
||||
|
||||
/// Global/static function listener.
|
||||
struct FunctionListener : public IListener
|
||||
{
|
||||
void (*f)();
|
||||
|
||||
void Call() { (*f)(); }
|
||||
|
||||
bool BelongsToInstance(void *) const { return false; }
|
||||
bool IsFunction(void (*_f)()) const { return f == _f; }
|
||||
|
||||
FunctionListener(void (*_f)()) : f(_f) {}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/// Return the number of listener on this signal.
|
||||
uint GetListenerCount() const { return listeners.GetCount(); }
|
||||
|
||||
/// Subscribe an instance member function to call when the event is triggered.
|
||||
template <class O> void Connect(O *i, void (O::*f)())
|
||||
{ listeners.Add(new InstanceListener <O> (i, f)); }
|
||||
/// Remove the subscription of all handlers associated with a specific class instance.
|
||||
template <class O> void Disconnect(O *i)
|
||||
{
|
||||
ListForeachPtr(IListener *, l, listeners)
|
||||
if (l->BelongsToInstance((void *)i))
|
||||
listeners.Remove(l);
|
||||
}
|
||||
|
||||
/// Subscribe a function to call when the event is triggered.
|
||||
void Connect(void (*f)())
|
||||
{ listeners.Add(new FunctionListener(f)); }
|
||||
/// Remove a function subscription.
|
||||
void Disconnect(void (*f)())
|
||||
{
|
||||
ListForeachPtr(IListener *, l, listeners)
|
||||
if (l->IsFunction(f))
|
||||
listeners.Remove(l);
|
||||
}
|
||||
|
||||
/// Emit the signal, notifies all listeners.
|
||||
void Emit() const
|
||||
{
|
||||
ListForeachPtr(IListener *, l, listeners)
|
||||
l->Call();
|
||||
}
|
||||
};
|
||||
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __SIGNAL__
|
||||
Reference in New Issue
Block a user