/* sigslot.h: Signal/Slot classes Written by Sarah Thompson (sarah@telergy.com) 2002. License: Public domain. You are free to use this code however you like, with the proviso that the author takes on no responsibility or liability for any use. QUICK DOCUMENTATION (see also the full documentation at http://sigslot.sourceforge.net/) 1. #define switches SIGSLOT_PURE_ISO: Define this to force ISO C++ compliance. This also disables all of the thread safety support on platforms where it is available. SIGSLOT_USE_POSIX_THREADS: Force use of Posix threads when using a C++ compiler other than gcc on a platform that supports Posix threads. (When using gcc, this is the default - use SIGSLOT_PURE_ISO to disable this if necessary) SIGSLOT_DEFAULT_MT_POLICY: Where thread support is enabled, this defaults to multi_threaded_global. Otherwise, the default is single_threaded. #define this yourself to override the default. In pure ISO mode, anything other than single_threaded will cause a compiler error. 2. PLATFORM NOTES Win32: On Win32, the WIN32 symbol must be #defined. Most mainstream compilers do this by default, but you may need to define it yourself if your build environment is less standard. This causes the Win32 thread support to be compiled in and used automatically. Unix/Linux/BSD, etc: If you're using gcc, it is assumed that you have Posix threads available, so they are used automatically. You can override this (as under Windows) with the SIGSLOT_PURE_ISO switch. If you're using something other than gcc but still want to use Posix threads, you need to #define SIGSLOT_USE_POSIX_THREADS. ISO C++: If none of the supported platforms are detected, or if SIGSLOT_PURE_ISO is defined, all multithreading support is turned off, along with any code that might cause a pure ISO C++ environment to complain. Before you ask, gcc -ansi -pedantic won't compile this library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of errors that aren't really there. If you feel like investigating this, please contact the author. THREADING MODES single_threaded: Your program is assumed to be single threaded from the point of view of signal/slot usage (i.e. all objects using signals and slots are created and destroyed from a single thread). Behaviour if objects are destroyed concurrently is undefined (i.e. you'll get the occasional segmentation fault/memory exception). multi_threaded_global: Your program is assumed to be multi threaded. Objects using signals and slots can be safely created and destroyed from any thread, even when connections exist. In multi_threaded_global mode, this is achieved by a single global mutex (actually a critical section on Windows because they are faster). This option uses less OS resources, but results in more opportunities for contention, possibly resulting in more context switches than are strictly necessary. multi_threaded_local: Behaviour in this mode is essentially the same as multi_threaded_global, except that each signal, and each object that inherits has_slots, all have their own mutex/critical section. In practice, this means that mutex collisions (and hence context switches) only happen if they are absolutely essential. However, on some platforms, creating a lot of mutexes can slow down the whole OS, so use this option with care. USING THE LIBRARY See the full documentation at http://sigslot.sourceforge.net/ */ #ifndef SIGSLOT_H #define SIGSLOT_H #include #include #include "tbb/spin_mutex.h" #define _SIGSLOT_HAS_TBB /* #if defined(SIGSLOT_PURE_ISO) || (!defined(WIN32) && !defined(__GNUG__) && !defined(SIGSLOT_USE_POSIX_THREADS)) # define _SIGSLOT_SINGLE_THREADED #elif defined(WIN32) # define _SIGSLOT_HAS_WIN32_THREADS # include #elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS) # define _SIGSLOT_HAS_POSIX_THREADS # include #else # define _SIGSLOT_SINGLE_THREADED #endif */ #ifndef SIGSLOT_DEFAULT_MT_POLICY # ifdef _SIGSLOT_SINGLE_THREADED # define SIGSLOT_DEFAULT_MT_POLICY single_threaded # else # define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local # endif #endif namespace sigslot { class single_threaded { public: single_threaded() { ; } virtual ~single_threaded() { ; } virtual void lock() { ; } virtual void unlock() { ; } }; #ifdef _SIGSLOT_HAS_WIN32_THREADS // The multi threading policies only get compiled in if they are enabled. class multi_threaded_global { public: multi_threaded_global() { static bool isinitialised = false; if(!isinitialised) { InitializeCriticalSection(get_critsec()); isinitialised = true; } } multi_threaded_global(const multi_threaded_global&) { ; } virtual ~multi_threaded_global() { ; } virtual void lock() { EnterCriticalSection(get_critsec()); } virtual void unlock() { LeaveCriticalSection(get_critsec()); } private: CRITICAL_SECTION* get_critsec() { static CRITICAL_SECTION g_critsec; return &g_critsec; } }; class multi_threaded_local { public: multi_threaded_local() { InitializeCriticalSection(&m_critsec); } multi_threaded_local(const multi_threaded_local&) { InitializeCriticalSection(&m_critsec); } virtual ~multi_threaded_local() { DeleteCriticalSection(&m_critsec); } virtual void lock() { EnterCriticalSection(&m_critsec); } virtual void unlock() { LeaveCriticalSection(&m_critsec); } private: CRITICAL_SECTION m_critsec; }; #endif // _SIGSLOT_HAS_WIN32_THREADS #ifdef _SIGSLOT_HAS_POSIX_THREADS // The multi threading policies only get compiled in if they are enabled. class multi_threaded_global { public: multi_threaded_global() { pthread_mutex_init(get_mutex(), NULL); } multi_threaded_global(const multi_threaded_global&) { ; } virtual ~multi_threaded_global() { ; } virtual void lock() { pthread_mutex_lock(get_mutex()); } virtual void unlock() { pthread_mutex_unlock(get_mutex()); } private: pthread_mutex_t* get_mutex() { static pthread_mutex_t g_mutex; return &g_mutex; } }; class multi_threaded_local { public: multi_threaded_local() { pthread_mutex_init(&m_mutex, NULL); } multi_threaded_local(const multi_threaded_local&) { pthread_mutex_init(&m_mutex, NULL); } virtual ~multi_threaded_local() { pthread_mutex_destroy(&m_mutex); } virtual void lock() { pthread_mutex_lock(&m_mutex); } virtual void unlock() { pthread_mutex_unlock(&m_mutex); } private: pthread_mutex_t m_mutex; }; #endif // _SIGSLOT_HAS_POSIX_THREADS #ifdef _SIGSLOT_HAS_TBB typedef tbb::spin_mutex tbb_mutex; // The multi threading policies only get compiled in if they are enabled. class multi_threaded_global { public: multi_threaded_global() { ; } multi_threaded_global(const multi_threaded_global&) { ; } virtual ~multi_threaded_global() { ; } virtual void lock() { get_mutex()->lock(); } virtual void unlock() { get_mutex()->unlock(); } private: tbb_mutex* get_mutex() { static tbb_mutex g_mutex; return &g_mutex; } }; class multi_threaded_local { public: multi_threaded_local() { ; } multi_threaded_local(const multi_threaded_local&) { ; } virtual ~multi_threaded_local() { ; } virtual void lock() { m_mutex.lock(); } virtual void unlock() { m_mutex.unlock(); } private: tbb_mutex m_mutex; }; #endif // _SIGSLOT_HAS_TBB template class lock_block { public: mt_policy* m_mutex; lock_block(mt_policy *mtx) : m_mutex(mtx) { m_mutex->lock(); } ~lock_block() { m_mutex->unlock(); } }; template class has_slots; template class _connection_base0 { public: virtual ~_connection_base0() {} virtual has_slots* getdest() const = 0; virtual void emitSignal() = 0; virtual _connection_base0* clone() = 0; virtual _connection_base0* duplicate(has_slots* pnewdest) = 0; }; template class _connection_base1 { public: virtual ~_connection_base1() {} virtual has_slots* getdest() const = 0; virtual void emitSignal(arg1_type) = 0; virtual _connection_base1* clone() = 0; virtual _connection_base1* duplicate(has_slots* pnewdest) = 0; }; template class _connection_base2 { public: virtual ~_connection_base2() {} virtual has_slots* getdest() const = 0; virtual void emitSignal(arg1_type, arg2_type) = 0; virtual _connection_base2* clone() = 0; virtual _connection_base2* duplicate(has_slots* pnewdest) = 0; }; template class _connection_base3 { public: virtual ~_connection_base3() {} virtual has_slots* getdest() const = 0; virtual void emitSignal(arg1_type, arg2_type, arg3_type) = 0; virtual _connection_base3* clone() = 0; virtual _connection_base3* duplicate(has_slots* pnewdest) = 0; }; template class _connection_base4 { public: virtual ~_connection_base4() {} virtual has_slots* getdest() const = 0; virtual void emitSignal(arg1_type, arg2_type, arg3_type, arg4_type) = 0; virtual _connection_base4* clone() = 0; virtual _connection_base4* duplicate(has_slots* pnewdest) = 0; }; template class _connection_base5 { public: virtual ~_connection_base5() {} virtual has_slots* getdest() const = 0; virtual void emitSignal(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type) = 0; virtual _connection_base5* clone() = 0; virtual _connection_base5* duplicate(has_slots* pnewdest) = 0; }; template class _connection_base6 { public: virtual ~_connection_base6() {} virtual has_slots* getdest() const = 0; virtual void emitSignal(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type) = 0; virtual _connection_base6* clone() = 0; virtual _connection_base6* duplicate(has_slots* pnewdest) = 0; }; template class _connection_base7 { public: virtual ~_connection_base7() {} virtual has_slots* getdest() const = 0; virtual void emitSignal(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type) = 0; virtual _connection_base7* clone() = 0; virtual _connection_base7* duplicate(has_slots* pnewdest) = 0; }; template class _connection_base8 { public: virtual ~_connection_base8() {} virtual has_slots* getdest() const = 0; virtual void emitSignal(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, arg8_type) = 0; virtual _connection_base8* clone() = 0; virtual _connection_base8* duplicate(has_slots* pnewdest) = 0; }; template class _signal_base : public mt_policy { public: virtual void slot_disconnect(has_slots* pslot) = 0; virtual void slot_duplicate(has_slots const* poldslot, has_slots* pnewslot) = 0; }; template class has_slots : public mt_policy { private: typedef typename std::set<_signal_base *> sender_set; typedef typename sender_set::const_iterator const_iterator; public: has_slots() {} has_slots(has_slots const& hs) : mt_policy(hs) { lock_block lock(this); const_iterator it = hs.m_senders.begin(); const_iterator itEnd = hs.m_senders.end(); while (it != itEnd) { (*it)->slot_duplicate(&hs, this); m_senders.insert(*it); ++it; } } void signal_connect(_signal_base* sender) { lock_block lock(this); m_senders.insert(sender); } void signal_disconnect(_signal_base* sender) { lock_block lock(this); m_senders.erase(sender); } virtual ~has_slots() { disconnect_all(); } void disconnect_all() { lock_block lock(this); const_iterator it = m_senders.begin(); const_iterator itEnd = m_senders.end(); while (it != itEnd) { (*it)->slot_disconnect(this); ++it; } m_senders.erase(m_senders.begin(), m_senders.end()); } private: sender_set m_senders; }; template class _signal_base0 : public _signal_base { public: typedef std::list<_connection_base0 *> connections_list; _signal_base0() {} _signal_base0(_signal_base0 const& s) : _signal_base(s) { lock_block lock(this); typename connections_list::const_iterator it = s.m_connected_slots.begin(); typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_connect(this); m_connected_slots.push_back((*it)->clone()); ++it; } } ~_signal_base0() { disconnect_all(); } void disconnect_all() { lock_block lock(this); typename connections_list::const_iterator it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_disconnect(this); delete *it; ++it; } m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); } void disconnect(has_slots* pclass) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == pclass) { delete *it; m_connected_slots.erase(it); pclass->signal_disconnect(this); return; } ++it; } } void slot_disconnect(has_slots* pslot) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { typename connections_list::iterator itNext = it; ++itNext; if ((*it)->getdest() == pslot) { m_connected_slots.erase(it); // delete *it; } it = itNext; } } void slot_duplicate(has_slots const* oldtarget, has_slots* newtarget) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == oldtarget) { m_connected_slots.push_back((*it)->duplicate(newtarget)); } ++it; } } protected: connections_list m_connected_slots; }; template class _signal_base1 : public _signal_base { public: typedef std::list<_connection_base1 *> connections_list; _signal_base1() {} _signal_base1(_signal_base1 const& s) : _signal_base(s) { lock_block lock(this); typename connections_list::const_iterator it = s.m_connected_slots.begin(); typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_connect(this); m_connected_slots.push_back((*it)->clone()); ++it; } } void slot_duplicate(has_slots const* oldtarget, has_slots* newtarget) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == oldtarget) { m_connected_slots.push_back((*it)->duplicate(newtarget)); } ++it; } } ~_signal_base1() { disconnect_all(); } void disconnect_all() { lock_block lock(this); typename connections_list::const_iterator it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_disconnect(this); delete *it; ++it; } m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); } void disconnect(has_slots* pclass) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == pclass) { delete *it; m_connected_slots.erase(it); pclass->signal_disconnect(this); return; } ++it; } } void slot_disconnect(has_slots* pslot) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { typename connections_list::iterator itNext = it; ++itNext; if ((*it)->getdest() == pslot) { m_connected_slots.erase(it); // delete *it; } it = itNext; } } protected: connections_list m_connected_slots; }; template class _signal_base2 : public _signal_base { public: typedef std::list<_connection_base2 *> connections_list; _signal_base2() {} _signal_base2(_signal_base2 const& s) : _signal_base(s) { lock_block lock(this); typename connections_list::const_iterator it = s.m_connected_slots.begin(); typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_connect(this); m_connected_slots.push_back((*it)->clone()); ++it; } } void slot_duplicate(has_slots const* oldtarget, has_slots* newtarget) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == oldtarget) { m_connected_slots.push_back((*it)->duplicate(newtarget)); } ++it; } } ~_signal_base2() { disconnect_all(); } void disconnect_all() { lock_block lock(this); typename connections_list::const_iterator it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_disconnect(this); delete *it; ++it; } m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); } void disconnect(has_slots* pclass) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == pclass) { delete *it; m_connected_slots.erase(it); pclass->signal_disconnect(this); return; } ++it; } } void slot_disconnect(has_slots* pslot) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { typename connections_list::iterator itNext = it; ++itNext; if ((*it)->getdest() == pslot) { m_connected_slots.erase(it); // delete *it; } it = itNext; } } protected: connections_list m_connected_slots; }; template class _signal_base3 : public _signal_base { public: typedef std::list<_connection_base3 *> connections_list; _signal_base3() {} _signal_base3(_signal_base3 const& s) : _signal_base(s) { lock_block lock(this); typename connections_list::const_iterator it = s.m_connected_slots.begin(); typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_connect(this); m_connected_slots.push_back((*it)->clone()); ++it; } } void slot_duplicate(has_slots const* oldtarget, has_slots* newtarget) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == oldtarget) { m_connected_slots.push_back((*it)->duplicate(newtarget)); } ++it; } } ~_signal_base3() { disconnect_all(); } void disconnect_all() { lock_block lock(this); typename connections_list::const_iterator it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_disconnect(this); delete *it; ++it; } m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); } void disconnect(has_slots* pclass) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == pclass) { delete *it; m_connected_slots.erase(it); pclass->signal_disconnect(this); return; } ++it; } } void slot_disconnect(has_slots* pslot) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { typename connections_list::iterator itNext = it; ++itNext; if ((*it)->getdest() == pslot) { m_connected_slots.erase(it); // delete *it; } it = itNext; } } protected: connections_list m_connected_slots; }; template class _signal_base4 : public _signal_base { public: typedef std::list<_connection_base4 *> connections_list; _signal_base4() {} _signal_base4(const _signal_base4& s) : _signal_base(s) { lock_block lock(this); typename connections_list::const_iterator it = s.m_connected_slots.begin(); typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_connect(this); m_connected_slots.push_back((*it)->clone()); ++it; } } void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == oldtarget) { m_connected_slots.push_back((*it)->duplicate(newtarget)); } ++it; } } ~_signal_base4() { disconnect_all(); } void disconnect_all() { lock_block lock(this); typename connections_list::const_iterator it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_disconnect(this); delete *it; ++it; } m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); } void disconnect(has_slots* pclass) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == pclass) { delete *it; m_connected_slots.erase(it); pclass->signal_disconnect(this); return; } ++it; } } void slot_disconnect(has_slots* pslot) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { typename connections_list::iterator itNext = it; ++itNext; if ((*it)->getdest() == pslot) { m_connected_slots.erase(it); // delete *it; } it = itNext; } } protected: connections_list m_connected_slots; }; template class _signal_base5 : public _signal_base { public: typedef std::list<_connection_base5 *> connections_list; _signal_base5() {} _signal_base5(const _signal_base5& s) : _signal_base(s) { lock_block lock(this); typename connections_list::const_iterator it = s.m_connected_slots.begin(); typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_connect(this); m_connected_slots.push_back((*it)->clone()); ++it; } } void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == oldtarget) { m_connected_slots.push_back((*it)->duplicate(newtarget)); } ++it; } } ~_signal_base5() { disconnect_all(); } void disconnect_all() { lock_block lock(this); typename connections_list::const_iterator it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_disconnect(this); delete *it; ++it; } m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); } void disconnect(has_slots* pclass) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == pclass) { delete *it; m_connected_slots.erase(it); pclass->signal_disconnect(this); return; } ++it; } } void slot_disconnect(has_slots* pslot) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { typename connections_list::iterator itNext = it; ++itNext; if ((*it)->getdest() == pslot) { m_connected_slots.erase(it); // delete *it; } it = itNext; } } protected: connections_list m_connected_slots; }; template class _signal_base6 : public _signal_base { public: typedef std::list<_connection_base6 *> connections_list; _signal_base6() {} _signal_base6(const _signal_base6& s) : _signal_base(s) { lock_block lock(this); typename connections_list::const_iterator it = s.m_connected_slots.begin(); typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_connect(this); m_connected_slots.push_back((*it)->clone()); ++it; } } void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == oldtarget) { m_connected_slots.push_back((*it)->duplicate(newtarget)); } ++it; } } ~_signal_base6() { disconnect_all(); } void disconnect_all() { lock_block lock(this); typename connections_list::const_iterator it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_disconnect(this); delete *it; ++it; } m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); } void disconnect(has_slots* pclass) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == pclass) { delete *it; m_connected_slots.erase(it); pclass->signal_disconnect(this); return; } ++it; } } void slot_disconnect(has_slots* pslot) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { typename connections_list::iterator itNext = it; ++itNext; if ((*it)->getdest() == pslot) { m_connected_slots.erase(it); // delete *it; } it = itNext; } } protected: connections_list m_connected_slots; }; template class _signal_base7 : public _signal_base { public: typedef std::list<_connection_base7 *> connections_list; _signal_base7() {} _signal_base7(const _signal_base7& s) : _signal_base(s) { lock_block lock(this); typename connections_list::const_iterator it = s.m_connected_slots.begin(); typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_connect(this); m_connected_slots.push_back((*it)->clone()); ++it; } } void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == oldtarget) m_connected_slots.push_back((*it)->duplicate(newtarget)); ++it; } } ~_signal_base7() { disconnect_all(); } void disconnect_all() { lock_block lock(this); typename connections_list::const_iterator it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_disconnect(this); delete *it; ++it; } m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); } void disconnect(has_slots* pclass) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == pclass) { delete *it; m_connected_slots.erase(it); pclass->signal_disconnect(this); return; } ++it; } } void slot_disconnect(has_slots* pslot) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { typename connections_list::iterator itNext = it; ++itNext; if ((*it)->getdest() == pslot) { m_connected_slots.erase(it); // delete *it; } it = itNext; } } protected: connections_list m_connected_slots; }; template class _signal_base8 : public _signal_base { public: typedef std::list<_connection_base8 *> connections_list; _signal_base8() {} _signal_base8(const _signal_base8& s) : _signal_base(s) { lock_block lock(this); typename connections_list::const_iterator it = s.m_connected_slots.begin(); typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_connect(this); m_connected_slots.push_back((*it)->clone()); ++it; } } void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == oldtarget) m_connected_slots.push_back((*it)->duplicate(newtarget)); ++it; } } ~_signal_base8() { disconnect_all(); } void disconnect_all() { lock_block lock(this); typename connections_list::const_iterator it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { (*it)->getdest()->signal_disconnect(this); delete *it; ++it; } m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); } void disconnect(has_slots* pclass) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { if ((*it)->getdest() == pclass) { delete *it; m_connected_slots.erase(it); pclass->signal_disconnect(this); return; } ++it; } } void slot_disconnect(has_slots* pslot) { lock_block lock(this); typename connections_list::iterator it = m_connected_slots.begin(); typename connections_list::iterator itEnd = m_connected_slots.end(); while (it != itEnd) { typename connections_list::iterator itNext = it; ++itNext; if ((*it)->getdest() == pslot) { m_connected_slots.erase(it); // delete *it; } it = itNext; } } protected: connections_list m_connected_slots; }; template class _connection0 : public _connection_base0 { public: _connection0() { m_pobject = NULL; m_pmemfun = NULL; } _connection0(dest_type* pobject, void (dest_type::*pmemfun)()) { m_pobject = pobject; m_pmemfun = pmemfun; } virtual _connection_base0* clone() { return new _connection0(*this); } virtual _connection_base0* duplicate(has_slots* pnewdest) { return new _connection0((dest_type *)pnewdest, m_pmemfun); } virtual void emitSignal() { (m_pobject->*m_pmemfun)(); } virtual has_slots* getdest() const { return m_pobject; } private: dest_type* m_pobject; void (dest_type::* m_pmemfun)(); }; template class _connection1 : public _connection_base1 { public: _connection1() { m_pobject = NULL; m_pmemfun = NULL; } _connection1(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type)) { m_pobject = pobject; m_pmemfun = pmemfun; } virtual _connection_base1* clone() { return new _connection1(*this); } virtual _connection_base1* duplicate(has_slots* pnewdest) { return new _connection1((dest_type *)pnewdest, m_pmemfun); } virtual void emitSignal(arg1_type a1) { (m_pobject->*m_pmemfun)(a1); } virtual has_slots* getdest() const { return m_pobject; } private: dest_type* m_pobject; void (dest_type::* m_pmemfun)(arg1_type); }; template class _connection2 : public _connection_base2 { public: _connection2() { m_pobject = NULL; m_pmemfun = NULL; } _connection2(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, arg2_type)) { m_pobject = pobject; m_pmemfun = pmemfun; } virtual _connection_base2* clone() { return new _connection2(*this); } virtual _connection_base2* duplicate(has_slots* pnewdest) { return new _connection2((dest_type *)pnewdest, m_pmemfun); } virtual void emitSignal(arg1_type a1, arg2_type a2) { (m_pobject->*m_pmemfun)(a1, a2); } virtual has_slots* getdest() const { return m_pobject; } private: dest_type* m_pobject; void (dest_type::* m_pmemfun)(arg1_type, arg2_type); }; template class _connection3 : public _connection_base3 { public: _connection3() { m_pobject = NULL; m_pmemfun = NULL; } _connection3(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, arg2_type, arg3_type)) { m_pobject = pobject; m_pmemfun = pmemfun; } virtual _connection_base3* clone() { return new _connection3(*this); } virtual _connection_base3* duplicate(has_slots* pnewdest) { return new _connection3((dest_type *)pnewdest, m_pmemfun); } virtual void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3) { (m_pobject->*m_pmemfun)(a1, a2, a3); } virtual has_slots* getdest() const { return m_pobject; } private: dest_type* m_pobject; void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type); }; template class _connection4 : public _connection_base4 { public: _connection4() { m_pobject = NULL; m_pmemfun = NULL; } _connection4(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type)) { m_pobject = pobject; m_pmemfun = pmemfun; } virtual _connection_base4* clone() { return new _connection4(*this); } virtual _connection_base4* duplicate(has_slots* pnewdest) { return new _connection4((dest_type *)pnewdest, m_pmemfun); } virtual void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) { (m_pobject->*m_pmemfun)(a1, a2, a3, a4); } virtual has_slots* getdest() const { return m_pobject; } private: dest_type* m_pobject; void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type); }; template class _connection5 : public _connection_base5 { public: _connection5() { m_pobject = NULL; m_pmemfun = NULL; } _connection5(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type)) { m_pobject = pobject; m_pmemfun = pmemfun; } virtual _connection_base5* clone() { return new _connection5(*this); } virtual _connection_base5* duplicate(has_slots* pnewdest) { return new _connection5((dest_type *)pnewdest, m_pmemfun); } virtual void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5) { (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5); } virtual has_slots* getdest() const { return m_pobject; } private: dest_type* m_pobject; void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type); }; template class _connection6 : public _connection_base6 { public: _connection6() { m_pobject = NULL; m_pmemfun = NULL; } _connection6(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type)) { m_pobject = pobject; m_pmemfun = pmemfun; } virtual _connection_base6* clone() { return new _connection6(*this); } virtual _connection_base6* duplicate(has_slots* pnewdest) { return new _connection6((dest_type *)pnewdest, m_pmemfun); } virtual void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6) { (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6); } virtual has_slots* getdest() const { return m_pobject; } private: dest_type* m_pobject; void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type); }; template class _connection7 : public _connection_base7 { public: _connection7() { m_pobject = NULL; m_pmemfun = NULL; } _connection7(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type)) { m_pobject = pobject; m_pmemfun = pmemfun; } virtual _connection_base7* clone() { return new _connection7(*this); } virtual _connection_base7* duplicate(has_slots* pnewdest) { return new _connection7((dest_type *)pnewdest, m_pmemfun); } virtual void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6, arg7_type a7) { (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7); } virtual has_slots* getdest() const { return m_pobject; } private: dest_type* m_pobject; void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type); }; template class _connection8 : public _connection_base8 { public: _connection8() { m_pobject = NULL; m_pmemfun = NULL; } _connection8(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, arg8_type)) { m_pobject = pobject; m_pmemfun = pmemfun; } virtual _connection_base8* clone() { return new _connection8(*this); } virtual _connection_base8* duplicate(has_slots* pnewdest) { return new _connection8((dest_type *)pnewdest, m_pmemfun); } virtual void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) { (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7, a8); } virtual has_slots* getdest() const { return m_pobject; } private: dest_type* m_pobject; void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, arg8_type); }; template class signal0 : public _signal_base0 { public: typedef _signal_base0 base; typedef typename base::connections_list connections_list; using base::m_connected_slots; signal0() {} signal0(const signal0& s) : _signal_base0(s) {} template void connect(desttype* pclass, void (desttype::*pmemfun)()) { lock_block lock(this); _connection0* conn = new _connection0(pclass, pmemfun); m_connected_slots.push_back(conn); pclass->signal_connect(this); } void emitSignal() { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(); it = itNext; } } void operator()() { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(); it = itNext; } } }; template class signal1 : public _signal_base1 { public: typedef _signal_base1 base; typedef typename base::connections_list connections_list; using base::m_connected_slots; signal1() {} signal1(const signal1& s) : _signal_base1(s) {} template void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type)) { lock_block lock(this); _connection1* conn = new _connection1(pclass, pmemfun); m_connected_slots.push_back(conn); pclass->signal_connect(this); } void emitSignal(arg1_type a1) { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(a1); it = itNext; } } void operator()(arg1_type a1) { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(a1); it = itNext; } } }; template class signal2 : public _signal_base2 { public: typedef _signal_base2 base; typedef typename base::connections_list connections_list; using base::m_connected_slots; signal2() {} signal2(const signal2& s) : _signal_base2(s) {} template void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, arg2_type)) { lock_block lock(this); _connection2* conn = new _connection2(pclass, pmemfun); m_connected_slots.push_back(conn); pclass->signal_connect(this); } void emitSignal(arg1_type a1, arg2_type a2) { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(a1, a2); it = itNext; } } void operator()(arg1_type a1, arg2_type a2) { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(a1, a2); it = itNext; } } }; template class signal3 : public _signal_base3 { public: typedef _signal_base3 base; typedef typename base::connections_list connections_list; using base::m_connected_slots; signal3() {} signal3(const signal3& s) : _signal_base3(s) {} template void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, arg2_type, arg3_type)) { lock_block lock(this); _connection3* conn = new _connection3(pclass, pmemfun); m_connected_slots.push_back(conn); pclass->signal_connect(this); } void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3) { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(a1, a2, a3); it = itNext; } } void operator()(arg1_type a1, arg2_type a2, arg3_type a3) { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(a1, a2, a3); it = itNext; } } }; template class signal4 : public _signal_base4 { public: typedef _signal_base4 base; typedef typename base::connections_list connections_list; using base::m_connected_slots; signal4() {} signal4(const signal4& s) : _signal_base4(s) {} template void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type)) { lock_block lock(this); _connection4* conn = new _connection4(pclass, pmemfun); m_connected_slots.push_back(conn); pclass->signal_connect(this); } void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(a1, a2, a3, a4); it = itNext; } } void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(a1, a2, a3, a4); it = itNext; } } }; template class signal5 : public _signal_base5 { public: typedef _signal_base5 base; typedef typename base::connections_list connections_list; using base::m_connected_slots; signal5() {} signal5(const signal5& s) : _signal_base5(s) {} template void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type)) { lock_block lock(this); _connection5* conn = new _connection5(pclass, pmemfun); m_connected_slots.push_back(conn); pclass->signal_connect(this); } void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5) { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(a1, a2, a3, a4, a5); it = itNext; } } void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5) { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(a1, a2, a3, a4, a5); it = itNext; } } }; template class signal6 : public _signal_base6 { public: typedef _signal_base6 base; typedef typename base::connections_list connections_list; using base::m_connected_slots; signal6() {} signal6(const signal6& s) : _signal_base6(s) {} template void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type)) { lock_block lock(this); _connection6* conn = new _connection6(pclass, pmemfun); m_connected_slots.push_back(conn); pclass->signal_connect(this); } void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6) { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(a1, a2, a3, a4, a5, a6); it = itNext; } } void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6) { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(a1, a2, a3, a4, a5, a6); it = itNext; } } }; template class signal7 : public _signal_base7 { public: typedef _signal_base7 base; typedef typename base::connections_list connections_list; using base::m_connected_slots; signal7() {} signal7(const signal7& s) : _signal_base7(s) {} template void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type)) { lock_block lock(this); _connection7* conn = new _connection7(pclass, pmemfun); m_connected_slots.push_back(conn); pclass->signal_connect(this); } void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6, arg7_type a7) { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(a1, a2, a3, a4, a5, a6, a7); it = itNext; } } void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6, arg7_type a7) { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(a1, a2, a3, a4, a5, a6, a7); it = itNext; } } }; template class signal8 : public _signal_base8 { public: typedef _signal_base8 base; typedef typename base::connections_list connections_list; using base::m_connected_slots; signal8() {} signal8(const signal8& s) : _signal_base8(s) {} template void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, arg8_type)) { lock_block lock(this); _connection8* conn = new _connection8(pclass, pmemfun); m_connected_slots.push_back(conn); pclass->signal_connect(this); } void emitSignal(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(a1, a2, a3, a4, a5, a6, a7, a8); it = itNext; } } void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) { lock_block lock(this); typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); typename connections_list::const_iterator itEnd = m_connected_slots.end(); while (it != itEnd) { itNext = it; ++itNext; (*it)->emitSignal(a1, a2, a3, a4, a5, a6, a7, a8); it = itNext; } } }; } // namespace sigslot #endif // SIGSLOT_H