diff --git a/horrible_cast.h b/horrible_cast.h index 7f44922..b24e42e 100644 --- a/horrible_cast.h +++ b/horrible_cast.h @@ -2,7 +2,7 @@ #define __horrible_cast_h__ -// horrible_union is used by {safe|dangerous}_horrible_cast to copy one arbitrary type to another +//horrible_union is used by {safe|dangerous}_horrible_cast to copy one arbitrary type to another template union horrible_union { diff --git a/signal.cpp b/signal.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/signal.h b/signal.h index e69de29..4870dd1 100644 --- a/signal.h +++ b/signal.h @@ -0,0 +1,134 @@ +#ifndef __Signal_h__ +#define __Signal_h__ + + + +#include "signal0.h" +#include "signal1.h" +#include "signal2.h" +#include "signal3.h" +#include "signal4.h" +#include "signal5.h" +#include "signal6.h" +#include "signal7.h" +#include "signal8.h" +#include "signal9.h" +#include "signal10.h" +#include "signal11.h" +#include "signal12.h" +#include "signal13.h" +#include "signal14.h" +#include "signal15.h" +#include "signal16.h" + + + +struct nilarg; + +template +class Signal : + public Signal16 +{ +}; + +template +class Signal : + public Signal15 +{ +}; + +template +class Signal : + public Signal14 +{ +}; + +template +class Signal : + public Signal13 +{ +}; + +template +class Signal : + public Signal12 +{ +}; + +template +class Signal : + public Signal11 +{ +}; + +template +class Signal : + public Signal10 +{ +}; + +template +class Signal : + public Signal9 +{ +}; + +template +class Signal : + public Signal8 +{ +}; + +template +class Signal : + public Signal7 +{ +}; + +template +class Signal : + public Signal6 +{ +}; + +template +class Signal : + public Signal5 +{ +}; + +template +class Signal : + public Signal4 +{ +}; + +template +class Signal : + public Signal3 +{ +}; + +template +class Signal : + public Signal2 +{ +}; + +template +class Signal : + public Signal1 +{ +}; + +template +class Signal : + public Signal0 +{ +}; + + +#include "signal/FixedArgSlot.h" + + +#endif // __Signal_h__ diff --git a/signal.pl b/signal.pl new file mode 100644 index 0000000..7714241 --- /dev/null +++ b/signal.pl @@ -0,0 +1,103 @@ +#!/usr/bin/perl + +############################################################## +# script to generate signal*.h files from signal_template.h +############################################################## + + +############################################## +# +# globals +# +############################################## + +# a variable to store our template text in +my $template = ""; + + +############################################## +# +# main() +# +############################################## + +# load template text (see bottom of script) +open(INFILE,") +{ + $template .= $_; +} +close(INFILE); + +# generate [signal0.h,signal16.h] +for (my $i=0;$i<=16;$i++) +{ + GenerateSignalXHeader($i); +} + + +############################################## +# +# Subroutines +# +############################################## + +# subroutine to generate one signal header file +sub GenerateSignalXHeader +{ + # only argument is number of template arguments to allow for this signal + my($nargs) = @_; + + # create a local copy of template text + my $file = $template; + + # create other substitution strings + my $narg_str = ""; + my $template_arg_decl_str = ""; + my $template_arg_str = ""; + my $formal_arg_decl_str = ""; + my $formal_arg_str = ""; + + # create subst string for # of args + $narg_str = sprintf("%d",$nargs); + + # create subst strings for template and function arguments + if ( $nargs > 0 ) + { + # template args follow T_return, so start with a comma + $template_arg_decl_str = ", "; + $template_arg_str = ", "; + + for (my $i=0;$i<($nargs-1);$i++) + { + # args with trailing comma + $template_arg_decl_str .= sprintf("typename T_arg%d, ",$i); + $template_arg_str .= sprintf("T_arg%d, ",$i); + $formal_arg_decl_str .= sprintf("T_arg%d a%d, ",$i,$i); + $formal_arg_str .= sprintf("a%d, ",$i); + } + + # args without trailing comma + $template_arg_decl_str .= sprintf("typename T_arg%d",$nargs-1); + $template_arg_str .= sprintf("T_arg%d",$nargs-1); + $formal_arg_decl_str .= sprintf("T_arg%d a%d",$nargs-1,$nargs-1); + $formal_arg_str .= sprintf("a%d",$nargs-1); + } + + # do substitution + $file =~ s/===NARG===/$narg_str/g; + $file =~ s/===TEMPLATE_ARG_DECL===/$template_arg_decl_str/g; + $file =~ s/===TEMPLATE_ARG===/$template_arg_str/g; + $file =~ s/===FORMAL_ARG_DECL===/$formal_arg_decl_str/g; + $file =~ s/===FORMAL_ARG===/$formal_arg_str/g; + + # create filename + my $filename = sprintf("signal%d.h",$nargs); + + # write file + open(OUTFILE,">$filename") || die; + print OUTFILE $file; + close(OUTFILE); +} + diff --git a/signal0.h b/signal0.h index ca15ee5..ec66e33 100644 --- a/signal0.h +++ b/signal0.h @@ -1,36 +1,181 @@ -#ifndef __signal0_h__ -#define __signal0_h__ - -#include "signal_base.h" -#include "slot.h" - -class signal0: public signal_base -{ - public: - /* - signal0(); - virtual ~signal0(); -*/ - - void operator() () const - { - // TODO: need a way to iterate the bound signal_base list ... - list_node* cur = head; - while(cur) - { - (cur->slot)(); - cur = cur->next; - } - } - - template - void connect(T_object* p_object, T_member p_member) - { - bind( slot0_method(p_object,p_member) ); - } -}; - -#include "signal0.inl" - -#endif // __signal0_h__ - + +#ifndef __Signal0_h__ +#define __Signal0_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 0 parameter(s). + */ +template +class Slot0 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() () const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot0_function: public Slot0 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(); + + Slot0_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() () const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot0_method: public Slot0 +{ + public: + + Slot0_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() () const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return > +class Signal0: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() () + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal0<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot0 pointer + Slot0* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot0* sNewFunc = new Slot0_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot0* sNewMethod = new Slot0_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot0_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot0_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal0_h__ diff --git a/signal0.inl b/signal0.inl deleted file mode 100644 index e69de29..0000000 diff --git a/signal1.h b/signal1.h new file mode 100644 index 0000000..dbab0b3 --- /dev/null +++ b/signal1.h @@ -0,0 +1,181 @@ + +#ifndef __Signal1_h__ +#define __Signal1_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 1 parameter(s). + */ +template +class Slot1 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (T_arg0 a0) const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot1_function: public Slot1 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0); + + Slot1_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (T_arg0 a0) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(a0); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot1_method: public Slot1 +{ + public: + + Slot1_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (T_arg0 a0) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(a0); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return, typename T_arg0 > +class Signal1: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() (T_arg0 a0) + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal1<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot1 pointer + Slot1* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(a0); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot1* sNewFunc = new Slot1_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot1* sNewMethod = new Slot1_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot1_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot1_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal1_h__ diff --git a/signal10.h b/signal10.h new file mode 100644 index 0000000..239251f --- /dev/null +++ b/signal10.h @@ -0,0 +1,181 @@ + +#ifndef __Signal10_h__ +#define __Signal10_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 10 parameter(s). + */ +template +class Slot10 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9) const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot10_function: public Slot10 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9); + + Slot10_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot10_method: public Slot10 +{ + public: + + Slot10_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return, typename T_arg0, typename T_arg1, typename T_arg2, typename T_arg3, typename T_arg4, typename T_arg5, typename T_arg6, typename T_arg7, typename T_arg8, typename T_arg9 > +class Signal10: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9) + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal10<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot10 pointer + Slot10* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot10* sNewFunc = new Slot10_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot10* sNewMethod = new Slot10_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot10_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot10_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal10_h__ diff --git a/signal11.h b/signal11.h new file mode 100644 index 0000000..02a2d57 --- /dev/null +++ b/signal11.h @@ -0,0 +1,181 @@ + +#ifndef __Signal11_h__ +#define __Signal11_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 11 parameter(s). + */ +template +class Slot11 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10) const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot11_function: public Slot11 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10); + + Slot11_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot11_method: public Slot11 +{ + public: + + Slot11_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return, typename T_arg0, typename T_arg1, typename T_arg2, typename T_arg3, typename T_arg4, typename T_arg5, typename T_arg6, typename T_arg7, typename T_arg8, typename T_arg9, typename T_arg10 > +class Signal11: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10) + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal11<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot11 pointer + Slot11* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot11* sNewFunc = new Slot11_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot11* sNewMethod = new Slot11_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot11_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot11_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal11_h__ diff --git a/signal12.h b/signal12.h new file mode 100644 index 0000000..e41aa3d --- /dev/null +++ b/signal12.h @@ -0,0 +1,181 @@ + +#ifndef __Signal12_h__ +#define __Signal12_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 12 parameter(s). + */ +template +class Slot12 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11) const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot12_function: public Slot12 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11); + + Slot12_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot12_method: public Slot12 +{ + public: + + Slot12_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return, typename T_arg0, typename T_arg1, typename T_arg2, typename T_arg3, typename T_arg4, typename T_arg5, typename T_arg6, typename T_arg7, typename T_arg8, typename T_arg9, typename T_arg10, typename T_arg11 > +class Signal12: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11) + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal12<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot12 pointer + Slot12* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot12* sNewFunc = new Slot12_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot12* sNewMethod = new Slot12_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot12_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot12_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal12_h__ diff --git a/signal13.h b/signal13.h new file mode 100644 index 0000000..a034cc4 --- /dev/null +++ b/signal13.h @@ -0,0 +1,181 @@ + +#ifndef __Signal13_h__ +#define __Signal13_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 13 parameter(s). + */ +template +class Slot13 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12) const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot13_function: public Slot13 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12); + + Slot13_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot13_method: public Slot13 +{ + public: + + Slot13_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return, typename T_arg0, typename T_arg1, typename T_arg2, typename T_arg3, typename T_arg4, typename T_arg5, typename T_arg6, typename T_arg7, typename T_arg8, typename T_arg9, typename T_arg10, typename T_arg11, typename T_arg12 > +class Signal13: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12) + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal13<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot13 pointer + Slot13* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot13* sNewFunc = new Slot13_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot13* sNewMethod = new Slot13_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot13_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot13_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal13_h__ diff --git a/signal14.h b/signal14.h new file mode 100644 index 0000000..1dc5785 --- /dev/null +++ b/signal14.h @@ -0,0 +1,181 @@ + +#ifndef __Signal14_h__ +#define __Signal14_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 14 parameter(s). + */ +template +class Slot14 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13) const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot14_function: public Slot14 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13); + + Slot14_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot14_method: public Slot14 +{ + public: + + Slot14_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return, typename T_arg0, typename T_arg1, typename T_arg2, typename T_arg3, typename T_arg4, typename T_arg5, typename T_arg6, typename T_arg7, typename T_arg8, typename T_arg9, typename T_arg10, typename T_arg11, typename T_arg12, typename T_arg13 > +class Signal14: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13) + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal14<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot14 pointer + Slot14* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot14* sNewFunc = new Slot14_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot14* sNewMethod = new Slot14_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot14_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot14_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal14_h__ diff --git a/signal15.h b/signal15.h new file mode 100644 index 0000000..c65f40f --- /dev/null +++ b/signal15.h @@ -0,0 +1,181 @@ + +#ifndef __Signal15_h__ +#define __Signal15_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 15 parameter(s). + */ +template +class Slot15 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13, T_arg14 a14) const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot15_function: public Slot15 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13, T_arg14 a14); + + Slot15_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13, T_arg14 a14) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot15_method: public Slot15 +{ + public: + + Slot15_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13, T_arg14 a14) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return, typename T_arg0, typename T_arg1, typename T_arg2, typename T_arg3, typename T_arg4, typename T_arg5, typename T_arg6, typename T_arg7, typename T_arg8, typename T_arg9, typename T_arg10, typename T_arg11, typename T_arg12, typename T_arg13, typename T_arg14 > +class Signal15: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13, T_arg14 a14) + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal15<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot15 pointer + Slot15* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13, T_arg14 a14); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot15* sNewFunc = new Slot15_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot15* sNewMethod = new Slot15_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot15_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot15_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal15_h__ diff --git a/signal16.h b/signal16.h new file mode 100644 index 0000000..bec9829 --- /dev/null +++ b/signal16.h @@ -0,0 +1,181 @@ + +#ifndef __Signal16_h__ +#define __Signal16_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 16 parameter(s). + */ +template +class Slot16 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13, T_arg14 a14, T_arg15 a15) const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot16_function: public Slot16 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13, T_arg14 a14, T_arg15 a15); + + Slot16_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13, T_arg14 a14, T_arg15 a15) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot16_method: public Slot16 +{ + public: + + Slot16_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13, T_arg14 a14, T_arg15 a15) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return, typename T_arg0, typename T_arg1, typename T_arg2, typename T_arg3, typename T_arg4, typename T_arg5, typename T_arg6, typename T_arg7, typename T_arg8, typename T_arg9, typename T_arg10, typename T_arg11, typename T_arg12, typename T_arg13, typename T_arg14, typename T_arg15 > +class Signal16: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13, T_arg14 a14, T_arg15 a15) + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal16<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot16 pointer + Slot16* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8, T_arg9 a9, T_arg10 a10, T_arg11 a11, T_arg12 a12, T_arg13 a13, T_arg14 a14, T_arg15 a15); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot16* sNewFunc = new Slot16_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot16* sNewMethod = new Slot16_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot16_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot16_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal16_h__ diff --git a/signal2.h b/signal2.h new file mode 100644 index 0000000..4b6f068 --- /dev/null +++ b/signal2.h @@ -0,0 +1,181 @@ + +#ifndef __Signal2_h__ +#define __Signal2_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 2 parameter(s). + */ +template +class Slot2 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (T_arg0 a0, T_arg1 a1) const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot2_function: public Slot2 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1); + + Slot2_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (T_arg0 a0, T_arg1 a1) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(a0, a1); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot2_method: public Slot2 +{ + public: + + Slot2_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (T_arg0 a0, T_arg1 a1) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(a0, a1); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return, typename T_arg0, typename T_arg1 > +class Signal2: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() (T_arg0 a0, T_arg1 a1) + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal2<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot2 pointer + Slot2* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(a0, a1); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot2* sNewFunc = new Slot2_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot2* sNewMethod = new Slot2_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot2_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot2_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal2_h__ diff --git a/signal3.h b/signal3.h new file mode 100644 index 0000000..154ece2 --- /dev/null +++ b/signal3.h @@ -0,0 +1,181 @@ + +#ifndef __Signal3_h__ +#define __Signal3_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 3 parameter(s). + */ +template +class Slot3 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2) const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot3_function: public Slot3 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2); + + Slot3_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(a0, a1, a2); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot3_method: public Slot3 +{ + public: + + Slot3_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(a0, a1, a2); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return, typename T_arg0, typename T_arg1, typename T_arg2 > +class Signal3: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2) + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal3<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot3 pointer + Slot3* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(a0, a1, a2); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot3* sNewFunc = new Slot3_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot3* sNewMethod = new Slot3_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot3_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot3_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal3_h__ diff --git a/signal4.h b/signal4.h new file mode 100644 index 0000000..76a1025 --- /dev/null +++ b/signal4.h @@ -0,0 +1,181 @@ + +#ifndef __Signal4_h__ +#define __Signal4_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 4 parameter(s). + */ +template +class Slot4 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3) const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot4_function: public Slot4 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3); + + Slot4_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(a0, a1, a2, a3); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot4_method: public Slot4 +{ + public: + + Slot4_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(a0, a1, a2, a3); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return, typename T_arg0, typename T_arg1, typename T_arg2, typename T_arg3 > +class Signal4: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3) + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal4<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot4 pointer + Slot4* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(a0, a1, a2, a3); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot4* sNewFunc = new Slot4_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot4* sNewMethod = new Slot4_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot4_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot4_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal4_h__ diff --git a/signal5.h b/signal5.h new file mode 100644 index 0000000..6fd958b --- /dev/null +++ b/signal5.h @@ -0,0 +1,181 @@ + +#ifndef __Signal5_h__ +#define __Signal5_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 5 parameter(s). + */ +template +class Slot5 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4) const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot5_function: public Slot5 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4); + + Slot5_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(a0, a1, a2, a3, a4); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot5_method: public Slot5 +{ + public: + + Slot5_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(a0, a1, a2, a3, a4); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return, typename T_arg0, typename T_arg1, typename T_arg2, typename T_arg3, typename T_arg4 > +class Signal5: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4) + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal5<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot5 pointer + Slot5* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(a0, a1, a2, a3, a4); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot5* sNewFunc = new Slot5_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot5* sNewMethod = new Slot5_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot5_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot5_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal5_h__ diff --git a/signal6.h b/signal6.h new file mode 100644 index 0000000..0537cb5 --- /dev/null +++ b/signal6.h @@ -0,0 +1,181 @@ + +#ifndef __Signal6_h__ +#define __Signal6_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 6 parameter(s). + */ +template +class Slot6 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5) const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot6_function: public Slot6 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5); + + Slot6_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(a0, a1, a2, a3, a4, a5); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot6_method: public Slot6 +{ + public: + + Slot6_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(a0, a1, a2, a3, a4, a5); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return, typename T_arg0, typename T_arg1, typename T_arg2, typename T_arg3, typename T_arg4, typename T_arg5 > +class Signal6: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5) + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal6<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot6 pointer + Slot6* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(a0, a1, a2, a3, a4, a5); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot6* sNewFunc = new Slot6_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot6* sNewMethod = new Slot6_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot6_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot6_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal6_h__ diff --git a/signal7.h b/signal7.h new file mode 100644 index 0000000..3e76419 --- /dev/null +++ b/signal7.h @@ -0,0 +1,181 @@ + +#ifndef __Signal7_h__ +#define __Signal7_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 7 parameter(s). + */ +template +class Slot7 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6) const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot7_function: public Slot7 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6); + + Slot7_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(a0, a1, a2, a3, a4, a5, a6); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot7_method: public Slot7 +{ + public: + + Slot7_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(a0, a1, a2, a3, a4, a5, a6); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return, typename T_arg0, typename T_arg1, typename T_arg2, typename T_arg3, typename T_arg4, typename T_arg5, typename T_arg6 > +class Signal7: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6) + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal7<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot7 pointer + Slot7* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(a0, a1, a2, a3, a4, a5, a6); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot7* sNewFunc = new Slot7_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot7* sNewMethod = new Slot7_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot7_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot7_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal7_h__ diff --git a/signal8.h b/signal8.h new file mode 100644 index 0000000..9cc81c6 --- /dev/null +++ b/signal8.h @@ -0,0 +1,181 @@ + +#ifndef __Signal8_h__ +#define __Signal8_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 8 parameter(s). + */ +template +class Slot8 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7) const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot8_function: public Slot8 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7); + + Slot8_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(a0, a1, a2, a3, a4, a5, a6, a7); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot8_method: public Slot8 +{ + public: + + Slot8_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(a0, a1, a2, a3, a4, a5, a6, a7); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return, typename T_arg0, typename T_arg1, typename T_arg2, typename T_arg3, typename T_arg4, typename T_arg5, typename T_arg6, typename T_arg7 > +class Signal8: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7) + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal8<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot8 pointer + Slot8* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(a0, a1, a2, a3, a4, a5, a6, a7); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot8* sNewFunc = new Slot8_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot8* sNewMethod = new Slot8_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot8_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot8_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal8_h__ diff --git a/signal9.h b/signal9.h new file mode 100644 index 0000000..b203d49 --- /dev/null +++ b/signal9.h @@ -0,0 +1,181 @@ + +#ifndef __Signal9_h__ +#define __Signal9_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + +//========================================================================================================================================= +// Slot tempplate. +//========================================================================================================================================= +/** + * Abstract base class for Slots with 9 parameter(s). + */ +template +class Slot9 : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8) const = 0; +}; + + +// +// a concrete Slot class for a normal function +// +template +class Slot9_function: public Slot9 +{ + public: + + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8); + + Slot9_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(a0, a1, a2, a3, a4, a5, a6, a7, a8); + } +}; + + +// +// a concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method') +// +template +class Slot9_method: public Slot9 +{ + public: + + Slot9_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(a0, a1, a2, a3, a4, a5, a6, a7, a8); + } +}; + +//========================================================================================================================================= +// Signal tempplate. +//========================================================================================================================================= +template< typename T_return, typename T_arg0, typename T_arg1, typename T_arg2, typename T_arg3, typename T_arg4, typename T_arg5, typename T_arg6, typename T_arg7, typename T_arg8 > +class Signal9: public signal_base +{ + public: + + //----------------------------------------------------------------------------------------------------------------------------------------- + // Execute the Signal: + // - Walk the list of Slot nodes. + //----------------------------------------------------------------------------------------------------------------------------------------- + void operator() (T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8) + { + if( IsSignalEmitting( ) ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal9<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + BeginEmit( ); + + list_node* cur = GetFirstNode( ); + + // iterate through the list + while( cur ) + { + // make the slot_base pointer a Slot9 pointer + Slot9* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(a0, a1, a2, a3, a4, a5, a6, a7, a8); + + // move to next Slot in the list. + cur = cur->next; + } + + EndEmit( ); + } + + //========================================================================================================================================= + // Signal connections + //========================================================================================================================================= + typedef T_return (*FUNCTION_POINTER)(T_arg0 a0, T_arg1 a1, T_arg2 a2, T_arg3 a3, T_arg4 a4, T_arg5 a5, T_arg6 a6, T_arg7 a7, T_arg8 a8); + + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot9* sNewFunc = new Slot9_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // Object methods + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot9* sNewMethod = new Slot9_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + //========================================================================================================================================= + // Signal Disconnections + //========================================================================================================================================= + // Functions + //----------------------------------------------------------------------------------------------------------------------------------------- + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot9_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + + // Object method + //----------------------------------------------------------------------------------------------------------------------------------------- + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot9_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __Signal9_h__ diff --git a/signal_base.cpp b/signal_base.cpp index 38a0a76..a310c31 100644 --- a/signal_base.cpp +++ b/signal_base.cpp @@ -1,151 +1,271 @@ -#include -#include "signal_base.h" - -signal_base::signal_base() : head(0), tail(0) -{ - // empty -} - -signal_base::~signal_base() -{ - // clear the list - clear_list(); -} - -bool signal_base::bind(const slot_base& slot) -{ - // add it to our signal list - return add_to_list(slot); -} - -bool signal_base::unbind(const slot_base& slot) -{ - // look for corresponding list_node in list - list_node* n = find_in_list(slot); - - // see if we found a match - if ( !n ) - { - return false; // no match found - } - - // take it out of the linked list - remove_from_list(n); - - // free it - delete n; - - // found a match, success - return true; -} - -void signal_base::clear_list() -{ - // start at head - list_node* cur = head; - - // iterate - while ( cur ) - { - // save off next so we can safely delete - list_node* next = cur->next; - - // free - delete cur; - - // advance - cur = next; - } - - // reset head & tail - head = tail = 0; -} - -signal_base::list_node* signal_base::find_in_list(const slot_base& slot) const -{ - // start search at head of list - list_node* cur = head; - - // search list for slot - while ( cur ) - { - // see if this is a match - if ( cur->slot == slot ) - { - // we have a match, return it - return cur; - } - - // advance to next in list - cur = cur->next; - } - - // no match - return 0; -} - -bool signal_base::add_to_list(const slot_base& slot) -{ - // a sanity check - assert((head && tail) || (!head && !tail)); - - // make a new list_node to hold this slot in the list - list_node* n = new list_node; - if ( !n ) - { - return false; - } - - // initialize new list_node - n->slot = slot; // copy slot into list_node - n->prev = tail; // prev is tail because we'll put this list_node behind it (i.e. the new tail) - n->next = 0; // next is 0 because we'll put this list_node on the tail - - // add to tail - if ( tail ) - { - // tail exists, just append - tail->next = n; // insert item after current tail - tail = n; // now have a new tail - } - else - { - // list is currently empty, add this new list_node - head = tail = n; // now have a single list_node, which is also both the head and tail - } - - return true; -} - -void signal_base::remove_from_list(list_node* n) -{ - // do a little sanity checking - assert((head && tail) || (!head && !tail)); - assert(n->prev == 0 || n->prev->next == n); - assert(n->next == 0 || n->next->prev == n); - - // if this is the head, set the new head - if ( n == head ) - { - head = n->next; - } - - // if this is the tail, set the new tail - if ( n == tail ) - { - tail = n->prev; - } - - // set list to skip over this list_node - if ( n->prev ) - { - n->prev->next = n->next; - } - if ( n->next ) - { - n->next->prev = n->prev; - } -} - - - +#include +#include "signal_base.h" + + +//----------------------------------------------------------------------------------------------------------------------------------------- +signal_base::signal_base() : head(0), tail(0), bEmitting(false) +{ + // empty +} + + +//----------------------------------------------------------------------------------------------------------------------------------------- +signal_base::~signal_base() +{ + // clear the list + clear_list(); +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +signal_base::signal_base( const signal_base& rSource ) : head(0), tail(0), bEmitting(false) +{ + // Set an assert to let the user know that we don't support construction of a signal by copying another one. + // There are too many places where the signals are directly connected to objects, where copying them would create a disconnect + // between the signal and the objects that want to react to the signal execution. + assert( 0 ); +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +signal_base& signal_base::operator=( const signal_base& rSource ) +{ + // Set an assert to let the user know that we don't support signal copying. + // There are too many places where the signals are directly connected to objects, where copying them would create a disconnect + // between the signal and the objects that want to react to the signal execution. + assert( 0 ); + return *this; +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +int signal_base::Count( void ) +{ + int Count = 0; + + list_node* pIndex; + pIndex = head; + + while( pIndex ) + { + pIndex = pIndex->next; + Count++; + } + + return Count; +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +bool signal_base::bind(slot_base* slot) +{ + // add it to our signal list + return add_to_list(slot); +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +bool signal_base::unbind(slot_base* slot) +{ + // look for corresponding list_node in list + list_node* n = find_in_list(slot); + + // see if we found a match + if( n ) + { + // If we are not processing a signal emit sequence, then release the node. + if( !IsSignalEmitting( ) ) + { + // take it out of the linked list + remove_from_list(n); + + // found a match, return success + return true; + } + // Otherwise mark it for removal. + else + { + n->bDeleteRequested = true; + return true; + } + } + + // no match + return false; +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +signal_base::list_node::list_node(slot_base* s) : slot(s), + prev(0), + next(0), + bDeleteRequested(false) +{ + // empty +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +signal_base::list_node::~list_node() +{ + // release the slot + delete slot; +} + + +//----------------------------------------------------------------------------------------------------------------------------------------- +signal_base::list_node* signal_base::GetFirstNode( void ) const +{ + return head; +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +void signal_base::clear_list() +{ + // start at head + list_node* cur = head; + + // iterate + while ( cur ) + { + // save off next so we can safely delete + list_node* next = cur->next; + + // free + delete cur; + + // advance + cur = next; + } + + // reset head & tail + head = tail = 0; +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +signal_base::list_node* signal_base::find_in_list(slot_base* slot) const +{ + // start search at head of list + list_node* cur = head; + + // search list for slot + while ( cur ) + { + // see if this is a match + if ( *(cur->slot) == *(slot) ) // note comparing values, not addresses !!! + { + // we have a match, return it + return cur; + } + + // advance to next in list + cur = cur->next; + } + + // no match + return 0; +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +bool signal_base::add_to_list(slot_base* slot) +{ + // a sanity check + assert((head && tail) || (!head && !tail)); + + // make a new list_node to hold this slot in the list + // and initialize with this slot pointer + list_node* node = new list_node(slot); + assert(node); + if ( !node ) + { + return false; + } + + // setup new list_node + node->prev = tail; // prev is tail because we'll put this list_node behind it (i.e. the new tail) + node->next = 0; // next is 0 because we'll put this list_node on the tail + + // add to tail + if ( tail ) + { + // tail exists, just append + tail->next = node; // insert item after current tail + tail = node; // now have a new tail + } + else + { + // list is currently empty, add this new list_node + head = tail = node; // now have a single list_node, which is also both the head and tail + } + + return true; +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +void signal_base::remove_from_list(list_node* n) +{ + // do a little sanity checking + assert((head && tail) || (!head && !tail)); + assert(n->prev == 0 || n->prev->next == n); + assert(n->next == 0 || n->next->prev == n); + + // if this is the head, set the new head + if ( n == head ) + { + head = n->next; + } + + // if this is the tail, set the new tail + if ( n == tail ) + { + tail = n->prev; + } + + // set list to skip over this list_node + if ( n->prev ) + { + n->prev->next = n->next; + } + if ( n->next ) + { + n->next->prev = n->prev; + } + + // finally, destroy the node + delete n; +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +void signal_base::remove_pending_nodes( void ) +{ + list_node* pIndex; + list_node* pNext; + + pIndex = head; + + while( pIndex ) + { + // Prepare the next link in the list the removal stage. + pNext = pIndex->next; + + // Do we need to remove this link. + if( pIndex->bDeleteRequested ) + remove_from_list( pIndex ); + + // Go to the next item. + pIndex = pNext; + } +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +void signal_base::BeginEmit( void ) +{ + bEmitting = true; +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +void signal_base::EndEmit( void ) +{ + bEmitting = false; + + remove_pending_nodes( ); +} + +//----------------------------------------------------------------------------------------------------------------------------------------- +bool signal_base::IsSignalEmitting( void ) const +{ + return bEmitting; +} diff --git a/signal_base.h b/signal_base.h index d032bad..736d385 100644 --- a/signal_base.h +++ b/signal_base.h @@ -1,38 +1,121 @@ -#ifndef __signal_base_h__ -#define __signal_base_h__ - -#include "slot_base.h" - -class signal_base -{ - public: - - signal_base(); - virtual ~signal_base(); - - protected: - - bool bind(const slot_base& slot); - bool unbind(const slot_base& slot); - -// TEMP HACK private: - - // linked list data structure - struct list_node - { - slot_base slot; - list_node* prev; - list_node* next; - }; - list_node* head; - list_node* tail; - - // linked list manipulation - void clear_list(); - list_node* find_in_list(const slot_base& slot) const; - bool add_to_list(const slot_base& slot); - void remove_from_list(list_node* n); -}; - -#endif // __signal_base_h__ - +#ifndef __signal_base_h__ +#define __signal_base_h__ + +#include "slot_base.h" + + +/** + * ----------------------------------------------------------------------------------------------------------------------------------------- + * Signals - An elegant system of that manages software events and the callbacks that respond to them. + * ----------------------------------------------------------------------------------------------------------------------------------------- + * + * Each discrete signal represents a moment within your application that might require some reaction. A signal might represent a + * basketball going through the basket, or hitting the ground. Another signal might identify when a bullet was fired out of a gun. + * There is no limit to what the signal represents. + * + * The reactions that need to be processed through the signal system are called "Slots". Slots are nothing more than a common interface + * that the Signal can use to call many variations of callbacks with a single interface. Some have labelled slots as "Delegates" as they are + * not the actual code that performs the reaction, but instead are used to translate the common reaction request into the actual callback that + * is desired. Please see slot_base.h for more information. + * + */ +class signal_base +{ + public: + + signal_base(); + virtual ~signal_base(); + + signal_base( const signal_base& rSource ); + signal_base& operator=( const signal_base& rSource ); + + /** + * Determines the number of slots that are connected to the signal. + */ + int Count( void ); + + protected: + // linked list data structure + // used to maintain a list of pointers to slot_base.. no memory management is + // performed on the slot_base data - derived class should take care of this. + struct list_node + { + list_node(slot_base* s); + ~list_node(); + + slot_base* slot; + list_node* prev; + list_node* next; + + bool bDeleteRequested; + }; + + /** + * Request to add a slot to the signals reaction list that is processed when a signal is executed. + * + * @param slot A pointer to a slot base class that contains the required callback mechanism. + * + * @return true if the signal is able to add the slot. + * false if the signal could NOT add the slot. + */ + bool bind(slot_base* slot); + + /** + * Request to remove a slot from the signals reaction list. + * + * @param slot A pointer to a slot base class that contains the required callback mechanism. + * + * @return true if the signal is able to remove the slot. + * false if the signal could NOT remove the slot. + */ + bool unbind(slot_base* slot); + + /** + * Used to obtain the first slot that is connected to this signal. Used for walking the list of slots when a signal is executed. + */ + list_node* GetFirstNode( void ) const; + + /** + * Functions used to maintain the status of a signal. When a signal is active it means that it is "Emitting". During the emitting + * stage, we are walking the list of slots to allow each slot to react to the signal. There are special considerations that + * must be made when walking the list, such as adding or removing slots during the emit stage. + */ + void BeginEmit( void ); + void EndEmit( void ); + bool IsSignalEmitting( void ) const; + + private: + /** + * Removes all slots that are connected to the signal + */ + void clear_list( ); + + /** + * Searches the slot list to find a slot that contains the same components. The location within the list is returned. + */ + list_node* find_in_list(slot_base* slot) const; + + /** + * Performs the actual operation of adding the slot to signal's internal list. + */ + bool add_to_list(slot_base* slot); + + /** + * Performs the actual operation of removing the slot from the signal's internal list. + */ + void remove_from_list(list_node* n); + + /** + * Removes any nodes that were tagged for deletion during the signal emit sequence + */ + void remove_pending_nodes( void ); + + //----------------------------------------------------------------------------------------------------------------------------------------- + list_node* head; + list_node* tail; + + bool bEmitting; +}; + +#endif // __signal_base_h__ + diff --git a/signal_template.h b/signal_template.h new file mode 100644 index 0000000..b214c5e --- /dev/null +++ b/signal_template.h @@ -0,0 +1,179 @@ +#ifndef __signal===NARG===_h__ +#define __signal===NARG===_h__ + +#include "horrible_cast.h" +#include "slot_base.h" +#include "signal_base.h" + + + +// +// Slot ===NARG=== +// + +// +// Abstract base class for Slots with ===NARG=== parameter(s). +// +template +class Slot===NARG=== : public slot_base +{ + public: + /** + * Method which performs the actual callback. Must be overridden. + * + * @return Returns an object of type T_return; the result of the user callback. + */ + virtual T_return operator() (===FORMAL_ARG_DECL===) const = 0; +}; + + +// +// A concrete Slot class for a normal function. +// +template +class Slot===NARG===_function: public Slot===NARG=== +{ + public: + + typedef T_return (*FUNCTION_POINTER)(===FORMAL_ARG_DECL===); + + Slot===NARG===_function( const FUNCTION_POINTER func ) + { + // convert and store function pointer in slot_base + this->data[0] = safe_horrible_cast(func); + } + + T_return operator() (===FORMAL_ARG_DECL===) const + { + // retrieve data from slot_base and convert back to a function pointer + FUNCTION_POINTER func = dangerous_horrible_cast(this->data[0]); + + // call function + return func(===FORMAL_ARG===); + } +}; + +// +// A concrete Slot class for an object pointer and method (usually 'this' and 'Class::Method'). +// +template +class Slot===NARG===_method: public Slot===NARG=== +{ + public: + + Slot===NARG===_method(const T_object* p_object, const T_member p_member) + { + // convert and store object pointer and member function pointer in slot_base + this->data[0] = safe_horrible_cast(p_object); + this->data[1] = safe_horrible_cast(p_member); + } + + T_return operator() (===FORMAL_ARG_DECL===) const + { + // retrieve data from slot_base and convert back to an object pointer and member function pointer + T_object* p_object = dangerous_horrible_cast(this->data[0]); + T_member p_member = dangerous_horrible_cast (this->data[1]); + + // call member function + return (p_object->*p_member)(===FORMAL_ARG===); + } +}; + + + +// +// Signal ===NARG=== +// +template< typename T_return===TEMPLATE_ARG_DECL=== > +class Signal===NARG===: public signal_base +{ + public: + + // Emit the signal. Iterate through the list of slots, and call each one. + void operator() (===FORMAL_ARG_DECL===) + { + // if we're already emitting, return (i.e. no re-entrancy) + if( IsSignalEmitting() ) + { +#if defined( _DEBUG ) + printf("WARNING: Signal===NARG===<...> @ 0x%p recursive Emit attempt\n", this); +#endif + return; + } + + // set emitting flag + BeginEmit(); + + // iterate through the list + list_node* cur = GetFirstNode(); + while( cur ) + { + // make the slot_base pointer a Slot===NARG=== pointer + Slot===NARG===* s = static_cast*>(cur->slot); + + // call the Signal + (*s)(===FORMAL_ARG===); + + // move to next Slot in the list. + cur = cur->next; + } + + // clear emitting flag + EndEmit( ); + } + + + // + // Signal connections + // + + // connect to normal functions + typedef T_return (*FUNCTION_POINTER)(===FORMAL_ARG_DECL===); // helper typedef + bool Connect( FUNCTION_POINTER func ) + { + // make a copy of the Slot to store in our list + Slot===NARG===* sNewFunc = new Slot===NARG===_function( func ); + + // add it to the end of our linked list + return bind(sNewFunc); + } + + // connect to an object's method + template + bool Connect(T_object* p_object, T_member p_member) + { + // make a copy of the Slot to store in our list + Slot===NARG===* sNewMethod = new Slot===NARG===_method( p_object, p_member ); + + // add it to the end of our linked list + return bind(sNewMethod); + } + + + // + // signal disconnections + // + + // disconnect from a normal function + bool Disconnect( FUNCTION_POINTER func ) + { + // make a temporary Slot we can use to find a match in the list + Slot===NARG===_function sTest( func ); + + // search and remove it + return unbind(&sTest); + } + + // disconnect from an object's method + template + bool Disconnect(T_object* p_object, T_member p_member) + { + // make a temporary Slot we can use to find a match in the list + Slot===NARG===_method sTemp(p_object,p_member); + + // search and remove it + return unbind(&sTemp); + } +}; + +#endif // __signal===NARG===_h__ diff --git a/slot_base.cpp b/slot_base.cpp index f6ab378..ed28cf9 100644 --- a/slot_base.cpp +++ b/slot_base.cpp @@ -3,9 +3,7 @@ bool slot_base::data_container::operator== (const slot_base::data_container& other) const { - // TODO: should use memcmp or equivalent - - // do a bytewise comparison + // do a wordwise comparison for (int i=0;idata[i] != other.data[i] ) @@ -27,7 +25,6 @@ void slot_base::data_container::zero() } } - slot_base::slot_base () { for (int i=0;i