sigslot的动态模板版本

来源:互联网 发布:dos下mac地址烧录工具 编辑:程序博客网 时间:2024/04/27 16:32

      拿到一个简单好用的库,但是里面使用了以前不支持动态模板的做法,写了很多重复代码。我用动态模板改进了一下,减少代码量。

原代码地址:http://sigslot.sourceforge.net/

// 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/)////#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.////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 <set>#include <list>#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 <windows.h>#elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS)#define _SIGSLOT_HAS_POSIX_THREADS#include <pthread.h>#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#endifnamespace 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_THREADStemplate<typename mt_policy>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<typename mt_policy>class has_slots;    template<typename mt_policy, typename ... Args>    class _connection_base_normal    {    public:        virtual has_slots<mt_policy>* getdest() const = 0;        virtual void emit(Args...) = 0;        virtual _connection_base_normal<mt_policy, Args...>* clone() = 0;        virtual _connection_base_normal<mt_policy, Args...>* duplicate(has_slots<mt_policy>* pnewdest) = 0;    };template<typename mt_policy>class _signal_base : public mt_policy{public:virtual void slot_disconnect(has_slots<mt_policy>* pslot) = 0;virtual void slot_duplicate(const has_slots<mt_policy>* poldslot, has_slots<mt_policy>* pnewslot) = 0;};template<typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>class has_slots : public mt_policy {private:typedef std::set<_signal_base<mt_policy>*> sender_set;        typedef typename sender_set::const_iterator set_const_iterator;public:has_slots(){;}has_slots(const has_slots& hs): mt_policy(hs){lock_block<mt_policy> lock(this);            set_const_iterator it = hs.m_senders.begin();            set_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<mt_policy>* sender){lock_block<mt_policy> lock(this);m_senders.insert(sender);}void signal_disconnect(_signal_base<mt_policy>* sender){lock_block<mt_policy> lock(this);m_senders.erase(sender);}virtual ~has_slots(){disconnect_all();}void disconnect_all(){lock_block<mt_policy> lock(this);            auto it = m_senders.begin();            auto 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<typename mt_policy, typename ... Args>class _signal_base_normal : public _signal_base<mt_policy>{public:        typedef std::list<_connection_base_normal<mt_policy, Args...> *>  connections_list;_signal_base_normal(){;}        _signal_base_normal(const _signal_base_normal<mt_policy, Args...>& s): _signal_base<mt_policy>(s){lock_block<mt_policy> lock(this);connections_list::const_iterator it = s.m_connected_slots.begin();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<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget){lock_block<mt_policy> lock(this);connections_list::iterator it = m_connected_slots.begin();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_base_normal(){disconnect_all();}void disconnect_all(){lock_block<mt_policy> lock(this);connections_list::const_iterator it = m_connected_slots.begin();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<mt_policy>* pclass){lock_block<mt_policy> lock(this);connections_list::iterator it = m_connected_slots.begin();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<mt_policy>* pslot){lock_block<mt_policy> lock(this);connections_list::iterator it = m_connected_slots.begin();connections_list::iterator itEnd = m_connected_slots.end();while(it != itEnd){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<typename dest_type, class mt_policy, typename ... Args>class _connection_normal : public _connection_base_normal<mt_policy, Args...>{public:_connection_normal(){pobject = NULL;pmemfun = NULL;}        _connection_normal(dest_type* pobject, void (dest_type::*pmemfun)(Args...)){m_pobject = pobject;m_pmemfun = pmemfun;}        virtual _connection_base_normal<mt_policy, Args...>* clone(){            return new _connection_normal<dest_type, mt_policy, Args...>(*this);}        virtual _connection_base_normal<mt_policy, Args...>* duplicate(has_slots<mt_policy>* pnewdest){            return new _connection_normal<dest_type, mt_policy, Args...>((dest_type *)pnewdest, m_pmemfun);}        virtual void emit(Args... args){            (m_pobject->*m_pmemfun)(args...);}virtual has_slots<mt_policy>* getdest() const{return m_pobject;}private:dest_type* m_pobject;void (dest_type::* m_pmemfun)(Args...);};template<typename mt_policy, typename ... Args>class signal_normal : public _signal_base_normal<mt_policy, Args...>{public:signal_normal(){;}        signal_normal(const signal_normal<mt_policy, Args...>& s)            : _signal_base_normal<mt_policy, Args...>(s){;}template<typename desttype>void connect(desttype* pclass, void (desttype::*pmemfun)(Args...)){lock_block<mt_policy> lock(this);_connection_normal<desttype, mt_policy, Args...>* conn = new _connection_normal<desttype, mt_policy, Args...>(pclass, pmemfun);m_connected_slots.push_back(conn);pclass->signal_connect(this);}void emit(Args...args){lock_block<mt_policy> lock(this);auto itNext = m_connected_slots.begin();            auto it = itNext;auto itEnd = m_connected_slots.end();while(it != itEnd){itNext = it;++itNext;                (*it)->emit(args...);it = itNext;}}void operator()(Args ...){lock_block<mt_policy> lock(this);connections_list::const_iterator itNext, it = m_connected_slots.begin();connections_list::const_iterator itEnd = m_connected_slots.end();while(it != itEnd){itNext = it;++itNext;(*it)->emit(Args...);it = itNext;}}};    template<typename ... Args>    class signal_defalut : public signal_normal <SIGSLOT_DEFAULT_MT_POLICY, Args... >    {    };}; // namespace sigslot#endif // SIGSLOT_H__


0 0
原创粉丝点击