1// sigslot.h: Signal/Slot classes
2//
3// Written by Sarah Thompson (sarah@telergy.com) 2002.
4//
5// License: Public domain. You are free to use this code however you like, with the proviso that
6//          the author takes on no responsibility or liability for any use.
7//
8// QUICK DOCUMENTATION
9//
10//				(see also the full documentation at http://sigslot.sourceforge.net/)
11//
12//		#define switches
13//			SIGSLOT_PURE_ISO			- Define this to force ISO C++ compliance. This also disables
14//										  all of the thread safety support on platforms where it is
15//										  available.
16//
17//			SIGSLOT_USE_POSIX_THREADS	- Force use of Posix threads when using a C++ compiler other than
18//										  gcc on a platform that supports Posix threads. (When using gcc,
19//										  this is the default - use SIGSLOT_PURE_ISO to disable this if
20//										  necessary)
21//
22//			SIGSLOT_DEFAULT_MT_POLICY	- Where thread support is enabled, this defaults to multi_threaded_global.
23//										  Otherwise, the default is single_threaded. #define this yourself to
24//										  override the default. In pure ISO mode, anything other than
25//										  single_threaded will cause a compiler error.
26//
27//		PLATFORM NOTES
28//
29//			Win32						- On Win32, the WEBRTC_WIN symbol must be #defined. Most mainstream
30//										  compilers do this by default, but you may need to define it
31//										  yourself if your build environment is less standard. This causes
32//										  the Win32 thread support to be compiled in and used automatically.
33//
34//			Unix/Linux/BSD, etc.		- If you're using gcc, it is assumed that you have Posix threads
35//										  available, so they are used automatically. You can override this
36//										  (as under Windows) with the SIGSLOT_PURE_ISO switch. If you're using
37//										  something other than gcc but still want to use Posix threads, you
38//										  need to #define SIGSLOT_USE_POSIX_THREADS.
39//
40//			ISO C++						- If none of the supported platforms are detected, or if
41//										  SIGSLOT_PURE_ISO is defined, all multithreading support is turned off,
42//										  along with any code that might cause a pure ISO C++ environment to
43//										  complain. Before you ask, gcc -ansi -pedantic won't compile this
44//										  library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of
45//										  errors that aren't really there. If you feel like investigating this,
46//										  please contact the author.
47//
48//
49//		THREADING MODES
50//
51//			single_threaded				- Your program is assumed to be single threaded from the point of view
52//										  of signal/slot usage (i.e. all objects using signals and slots are
53//										  created and destroyed from a single thread). Behaviour if objects are
54//										  destroyed concurrently is undefined (i.e. you'll get the occasional
55//										  segmentation fault/memory exception).
56//
57//			multi_threaded_global		- Your program is assumed to be multi threaded. Objects using signals and
58//										  slots can be safely created and destroyed from any thread, even when
59//										  connections exist. In multi_threaded_global mode, this is achieved by a
60//										  single global mutex (actually a critical section on Windows because they
61//										  are faster). This option uses less OS resources, but results in more
62//										  opportunities for contention, possibly resulting in more context switches
63//										  than are strictly necessary.
64//
65//			multi_threaded_local		- Behaviour in this mode is essentially the same as multi_threaded_global,
66//										  except that each signal, and each object that inherits has_slots, all
67//										  have their own mutex/critical section. In practice, this means that
68//										  mutex collisions (and hence context switches) only happen if they are
69//										  absolutely essential. However, on some platforms, creating a lot of
70//										  mutexes can slow down the whole OS, so use this option with care.
71//
72//		USING THE LIBRARY
73//
74//			See the full documentation at http://sigslot.sourceforge.net/
75//
76//
77// Libjingle specific:
78// This file has been modified such that has_slots and signalx do not have to be
79// using the same threading requirements. E.g. it is possible to connect a
80// has_slots<single_threaded> and signal0<multi_threaded_local> or
81// has_slots<multi_threaded_local> and signal0<single_threaded>.
82// If has_slots is single threaded the user must ensure that it is not trying
83// to connect or disconnect to signalx concurrently or data race may occur.
84// If signalx is single threaded the user must ensure that disconnect, connect
85// or signal is not happening concurrently or data race may occur.
86
87#ifndef WEBRTC_BASE_SIGSLOT_H__
88#define WEBRTC_BASE_SIGSLOT_H__
89
90#include <list>
91#include <set>
92#include <stdlib.h>
93
94// On our copy of sigslot.h, we set single threading as default.
95#define SIGSLOT_DEFAULT_MT_POLICY single_threaded
96
97#if defined(SIGSLOT_PURE_ISO) || (!defined(WEBRTC_WIN) && !defined(__GNUG__) && !defined(SIGSLOT_USE_POSIX_THREADS))
98#	define _SIGSLOT_SINGLE_THREADED
99#elif defined(WEBRTC_WIN)
100#	define _SIGSLOT_HAS_WIN32_THREADS
101#	if !defined(WIN32_LEAN_AND_MEAN)
102#		define WIN32_LEAN_AND_MEAN
103#	endif
104#	include "webrtc/base/win32.h"
105#elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS)
106#	define _SIGSLOT_HAS_POSIX_THREADS
107#	include <pthread.h>
108#else
109#	define _SIGSLOT_SINGLE_THREADED
110#endif
111
112#ifndef SIGSLOT_DEFAULT_MT_POLICY
113#	ifdef _SIGSLOT_SINGLE_THREADED
114#		define SIGSLOT_DEFAULT_MT_POLICY single_threaded
115#	else
116#		define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local
117#	endif
118#endif
119
120// TODO: change this namespace to rtc?
121namespace sigslot {
122
123	class single_threaded
124	{
125	public:
126		single_threaded()
127		{
128			;
129		}
130
131		virtual ~single_threaded()
132		{
133			;
134		}
135
136		virtual void lock()
137		{
138			;
139		}
140
141		virtual void unlock()
142		{
143			;
144		}
145	};
146
147#ifdef _SIGSLOT_HAS_WIN32_THREADS
148	// The multi threading policies only get compiled in if they are enabled.
149	class multi_threaded_global
150	{
151	public:
152		multi_threaded_global()
153		{
154			static bool isinitialised = false;
155
156			if(!isinitialised)
157			{
158				InitializeCriticalSection(get_critsec());
159				isinitialised = true;
160			}
161		}
162
163		multi_threaded_global(const multi_threaded_global&)
164		{
165			;
166		}
167
168		virtual ~multi_threaded_global()
169		{
170			;
171		}
172
173		virtual void lock()
174		{
175			EnterCriticalSection(get_critsec());
176		}
177
178		virtual void unlock()
179		{
180			LeaveCriticalSection(get_critsec());
181		}
182
183	private:
184		CRITICAL_SECTION* get_critsec()
185		{
186			static CRITICAL_SECTION g_critsec;
187			return &g_critsec;
188		}
189	};
190
191	class multi_threaded_local
192	{
193	public:
194		multi_threaded_local()
195		{
196			InitializeCriticalSection(&m_critsec);
197		}
198
199		multi_threaded_local(const multi_threaded_local&)
200		{
201			InitializeCriticalSection(&m_critsec);
202		}
203
204		virtual ~multi_threaded_local()
205		{
206			DeleteCriticalSection(&m_critsec);
207		}
208
209		virtual void lock()
210		{
211			EnterCriticalSection(&m_critsec);
212		}
213
214		virtual void unlock()
215		{
216			LeaveCriticalSection(&m_critsec);
217		}
218
219	private:
220		CRITICAL_SECTION m_critsec;
221	};
222#endif // _SIGSLOT_HAS_WIN32_THREADS
223
224#ifdef _SIGSLOT_HAS_POSIX_THREADS
225	// The multi threading policies only get compiled in if they are enabled.
226	class multi_threaded_global
227	{
228	public:
229		multi_threaded_global()
230		{
231			pthread_mutex_init(get_mutex(), NULL);
232		}
233
234		multi_threaded_global(const multi_threaded_global&)
235		{
236			;
237		}
238
239		virtual ~multi_threaded_global()
240		{
241			;
242		}
243
244		virtual void lock()
245		{
246			pthread_mutex_lock(get_mutex());
247		}
248
249		virtual void unlock()
250		{
251			pthread_mutex_unlock(get_mutex());
252		}
253
254	private:
255		pthread_mutex_t* get_mutex()
256		{
257			static pthread_mutex_t g_mutex;
258			return &g_mutex;
259		}
260	};
261
262	class multi_threaded_local
263	{
264	public:
265		multi_threaded_local()
266		{
267			pthread_mutex_init(&m_mutex, NULL);
268		}
269
270		multi_threaded_local(const multi_threaded_local&)
271		{
272			pthread_mutex_init(&m_mutex, NULL);
273		}
274
275		virtual ~multi_threaded_local()
276		{
277			pthread_mutex_destroy(&m_mutex);
278		}
279
280		virtual void lock()
281		{
282			pthread_mutex_lock(&m_mutex);
283		}
284
285		virtual void unlock()
286		{
287			pthread_mutex_unlock(&m_mutex);
288		}
289
290	private:
291		pthread_mutex_t m_mutex;
292	};
293#endif // _SIGSLOT_HAS_POSIX_THREADS
294
295	template<class mt_policy>
296	class lock_block
297	{
298	public:
299		mt_policy *m_mutex;
300
301		lock_block(mt_policy *mtx)
302			: m_mutex(mtx)
303		{
304			m_mutex->lock();
305		}
306
307		~lock_block()
308		{
309			m_mutex->unlock();
310		}
311	};
312
313	class has_slots_interface;
314
315	template<class mt_policy>
316	class _connection_base0
317	{
318	public:
319		virtual ~_connection_base0() {}
320		virtual has_slots_interface* getdest() const = 0;
321		virtual void emit() = 0;
322		virtual _connection_base0* clone() = 0;
323		virtual _connection_base0* duplicate(has_slots_interface* pnewdest) = 0;
324	};
325
326	template<class arg1_type, class mt_policy>
327	class _connection_base1
328	{
329	public:
330		virtual ~_connection_base1() {}
331		virtual has_slots_interface* getdest() const = 0;
332		virtual void emit(arg1_type) = 0;
333		virtual _connection_base1<arg1_type, mt_policy>* clone() = 0;
334		virtual _connection_base1<arg1_type, mt_policy>* duplicate(has_slots_interface* pnewdest) = 0;
335	};
336
337	template<class arg1_type, class arg2_type, class mt_policy>
338	class _connection_base2
339	{
340	public:
341		virtual ~_connection_base2() {}
342		virtual has_slots_interface* getdest() const = 0;
343		virtual void emit(arg1_type, arg2_type) = 0;
344		virtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone() = 0;
345		virtual _connection_base2<arg1_type, arg2_type, mt_policy>* duplicate(has_slots_interface* pnewdest) = 0;
346	};
347
348	template<class arg1_type, class arg2_type, class arg3_type, class mt_policy>
349	class _connection_base3
350	{
351	public:
352		virtual ~_connection_base3() {}
353		virtual has_slots_interface* getdest() const = 0;
354		virtual void emit(arg1_type, arg2_type, arg3_type) = 0;
355		virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* clone() = 0;
356		virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* duplicate(has_slots_interface* pnewdest) = 0;
357	};
358
359	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy>
360	class _connection_base4
361	{
362	public:
363		virtual ~_connection_base4() {}
364		virtual has_slots_interface* getdest() const = 0;
365		virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type) = 0;
366		virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* clone() = 0;
367		virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* duplicate(has_slots_interface* pnewdest) = 0;
368	};
369
370	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
371	class arg5_type, class mt_policy>
372	class _connection_base5
373	{
374	public:
375		virtual ~_connection_base5() {}
376		virtual has_slots_interface* getdest() const = 0;
377		virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type,
378			arg5_type) = 0;
379		virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,
380			arg5_type, mt_policy>* clone() = 0;
381		virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,
382			arg5_type, mt_policy>* duplicate(has_slots_interface* pnewdest) = 0;
383	};
384
385	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
386	class arg5_type, class arg6_type, class mt_policy>
387	class _connection_base6
388	{
389	public:
390		virtual ~_connection_base6() {}
391		virtual has_slots_interface* getdest() const = 0;
392		virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,
393			arg6_type) = 0;
394		virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,
395			arg5_type, arg6_type, mt_policy>* clone() = 0;
396		virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,
397			arg5_type, arg6_type, mt_policy>* duplicate(has_slots_interface* pnewdest) = 0;
398	};
399
400	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
401	class arg5_type, class arg6_type, class arg7_type, class mt_policy>
402	class _connection_base7
403	{
404	public:
405		virtual ~_connection_base7() {}
406		virtual has_slots_interface* getdest() const = 0;
407		virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,
408			arg6_type, arg7_type) = 0;
409		virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,
410			arg5_type, arg6_type, arg7_type, mt_policy>* clone() = 0;
411		virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,
412			arg5_type, arg6_type, arg7_type, mt_policy>* duplicate(has_slots_interface* pnewdest) = 0;
413	};
414
415	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
416	class arg5_type, class arg6_type, class arg7_type, class arg8_type, class mt_policy>
417	class _connection_base8
418	{
419	public:
420		virtual ~_connection_base8() {}
421		virtual has_slots_interface* getdest() const = 0;
422		virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,
423			arg6_type, arg7_type, arg8_type) = 0;
424		virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,
425			arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* clone() = 0;
426		virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,
427			arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* duplicate(has_slots_interface* pnewdest) = 0;
428	};
429
430	class _signal_base_interface
431	{
432	public:
433		virtual void slot_disconnect(has_slots_interface* pslot) = 0;
434		virtual void slot_duplicate(const has_slots_interface* poldslot, has_slots_interface* pnewslot) = 0;
435	};
436
437	template<class mt_policy>
438	class _signal_base : public _signal_base_interface, public mt_policy
439	{
440	};
441
442	class has_slots_interface
443	{
444	public:
445		has_slots_interface()
446		{
447			;
448		}
449
450		virtual void signal_connect(_signal_base_interface* sender) = 0;
451
452		virtual void signal_disconnect(_signal_base_interface* sender) = 0;
453
454		virtual ~has_slots_interface()
455		{
456		}
457
458		virtual void disconnect_all() = 0;
459	};
460
461	template<class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
462	class has_slots : public has_slots_interface, public mt_policy
463	{
464	private:
465		typedef std::set<_signal_base_interface*> sender_set;
466		typedef sender_set::const_iterator const_iterator;
467
468	public:
469		has_slots()
470		{
471			;
472		}
473
474		has_slots(const has_slots& hs)
475		{
476			lock_block<mt_policy> lock(this);
477			const_iterator it = hs.m_senders.begin();
478			const_iterator itEnd = hs.m_senders.end();
479
480			while(it != itEnd)
481			{
482				(*it)->slot_duplicate(&hs, this);
483				m_senders.insert(*it);
484				++it;
485			}
486		}
487
488		void signal_connect(_signal_base_interface* sender)
489		{
490			lock_block<mt_policy> lock(this);
491			m_senders.insert(sender);
492		}
493
494		void signal_disconnect(_signal_base_interface* sender)
495		{
496			lock_block<mt_policy> lock(this);
497			m_senders.erase(sender);
498		}
499
500		virtual ~has_slots()
501		{
502			disconnect_all();
503		}
504
505		void disconnect_all()
506		{
507			lock_block<mt_policy> lock(this);
508			const_iterator it = m_senders.begin();
509			const_iterator itEnd = m_senders.end();
510
511			while(it != itEnd)
512			{
513				(*it)->slot_disconnect(this);
514				++it;
515			}
516
517			m_senders.erase(m_senders.begin(), m_senders.end());
518		}
519
520	private:
521		sender_set m_senders;
522	};
523
524	template<class mt_policy>
525	class _signal_base0 : public _signal_base<mt_policy>
526	{
527	public:
528		typedef std::list<_connection_base0<mt_policy> *>  connections_list;
529
530		_signal_base0()
531		{
532			;
533		}
534
535		_signal_base0(const _signal_base0& s)
536			: _signal_base<mt_policy>(s)
537		{
538			lock_block<mt_policy> lock(this);
539			typename connections_list::const_iterator it = s.m_connected_slots.begin();
540			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
541
542			while(it != itEnd)
543			{
544				(*it)->getdest()->signal_connect(this);
545				m_connected_slots.push_back((*it)->clone());
546
547				++it;
548			}
549		}
550
551		~_signal_base0()
552		{
553			disconnect_all();
554		}
555
556		bool is_empty()
557		{
558			lock_block<mt_policy> lock(this);
559			typename connections_list::const_iterator it = m_connected_slots.begin();
560			typename connections_list::const_iterator itEnd = m_connected_slots.end();
561			return it == itEnd;
562		}
563
564		void disconnect_all()
565		{
566			lock_block<mt_policy> lock(this);
567			typename connections_list::const_iterator it = m_connected_slots.begin();
568			typename connections_list::const_iterator itEnd = m_connected_slots.end();
569
570			while(it != itEnd)
571			{
572				(*it)->getdest()->signal_disconnect(this);
573				delete *it;
574
575				++it;
576			}
577
578			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
579		}
580
581#ifdef _DEBUG
582			bool connected(has_slots_interface* pclass)
583		{
584			lock_block<mt_policy> lock(this);
585			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
586			typename connections_list::const_iterator itEnd = m_connected_slots.end();
587			while(it != itEnd)
588			{
589				itNext = it;
590				++itNext;
591				if ((*it)->getdest() == pclass)
592					return true;
593				it = itNext;
594			}
595			return false;
596		}
597#endif
598
599		void disconnect(has_slots_interface* pclass)
600		{
601			lock_block<mt_policy> lock(this);
602			typename connections_list::iterator it = m_connected_slots.begin();
603			typename connections_list::iterator itEnd = m_connected_slots.end();
604
605			while(it != itEnd)
606			{
607				if((*it)->getdest() == pclass)
608				{
609					delete *it;
610					m_connected_slots.erase(it);
611					pclass->signal_disconnect(this);
612					return;
613				}
614
615				++it;
616			}
617		}
618
619		void slot_disconnect(has_slots_interface* pslot)
620		{
621			lock_block<mt_policy> lock(this);
622			typename connections_list::iterator it = m_connected_slots.begin();
623			typename connections_list::iterator itEnd = m_connected_slots.end();
624
625			while(it != itEnd)
626			{
627				typename connections_list::iterator itNext = it;
628				++itNext;
629
630				if((*it)->getdest() == pslot)
631				{
632					delete *it;
633					m_connected_slots.erase(it);
634				}
635
636				it = itNext;
637			}
638		}
639
640		void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget)
641		{
642			lock_block<mt_policy> lock(this);
643			typename connections_list::iterator it = m_connected_slots.begin();
644			typename connections_list::iterator itEnd = m_connected_slots.end();
645
646			while(it != itEnd)
647			{
648				if((*it)->getdest() == oldtarget)
649				{
650					m_connected_slots.push_back((*it)->duplicate(newtarget));
651				}
652
653				++it;
654			}
655		}
656
657	protected:
658		connections_list m_connected_slots;
659	};
660
661	template<class arg1_type, class mt_policy>
662	class _signal_base1 : public _signal_base<mt_policy>
663	{
664	public:
665		typedef std::list<_connection_base1<arg1_type, mt_policy> *>  connections_list;
666
667		_signal_base1()
668		{
669			;
670		}
671
672		_signal_base1(const _signal_base1<arg1_type, mt_policy>& s)
673			: _signal_base<mt_policy>(s)
674		{
675			lock_block<mt_policy> lock(this);
676			typename connections_list::const_iterator it = s.m_connected_slots.begin();
677			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
678
679			while(it != itEnd)
680			{
681				(*it)->getdest()->signal_connect(this);
682				m_connected_slots.push_back((*it)->clone());
683
684				++it;
685			}
686		}
687
688		void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget)
689		{
690			lock_block<mt_policy> lock(this);
691			typename connections_list::iterator it = m_connected_slots.begin();
692			typename connections_list::iterator itEnd = m_connected_slots.end();
693
694			while(it != itEnd)
695			{
696				if((*it)->getdest() == oldtarget)
697				{
698					m_connected_slots.push_back((*it)->duplicate(newtarget));
699				}
700
701				++it;
702			}
703		}
704
705		~_signal_base1()
706		{
707			disconnect_all();
708		}
709
710		bool is_empty()
711		{
712			lock_block<mt_policy> lock(this);
713			typename connections_list::const_iterator it = m_connected_slots.begin();
714			typename connections_list::const_iterator itEnd = m_connected_slots.end();
715			return it == itEnd;
716		}
717
718		void disconnect_all()
719		{
720			lock_block<mt_policy> lock(this);
721			typename connections_list::const_iterator it = m_connected_slots.begin();
722			typename connections_list::const_iterator itEnd = m_connected_slots.end();
723
724			while(it != itEnd)
725			{
726				(*it)->getdest()->signal_disconnect(this);
727				delete *it;
728
729				++it;
730			}
731
732			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
733		}
734
735#ifdef _DEBUG
736			bool connected(has_slots_interface* pclass)
737		{
738			lock_block<mt_policy> lock(this);
739			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
740			typename connections_list::const_iterator itEnd = m_connected_slots.end();
741			while(it != itEnd)
742			{
743				itNext = it;
744				++itNext;
745				if ((*it)->getdest() == pclass)
746					return true;
747				it = itNext;
748			}
749			return false;
750		}
751#endif
752
753		void disconnect(has_slots_interface* pclass)
754		{
755			lock_block<mt_policy> lock(this);
756			typename connections_list::iterator it = m_connected_slots.begin();
757			typename connections_list::iterator itEnd = m_connected_slots.end();
758
759			while(it != itEnd)
760			{
761				if((*it)->getdest() == pclass)
762				{
763					delete *it;
764					m_connected_slots.erase(it);
765					pclass->signal_disconnect(this);
766					return;
767				}
768
769				++it;
770			}
771		}
772
773		void slot_disconnect(has_slots_interface* pslot)
774		{
775			lock_block<mt_policy> lock(this);
776			typename connections_list::iterator it = m_connected_slots.begin();
777			typename connections_list::iterator itEnd = m_connected_slots.end();
778
779			while(it != itEnd)
780			{
781				typename connections_list::iterator itNext = it;
782				++itNext;
783
784				if((*it)->getdest() == pslot)
785				{
786					delete *it;
787					m_connected_slots.erase(it);
788				}
789
790				it = itNext;
791			}
792		}
793
794
795	protected:
796		connections_list m_connected_slots;
797	};
798
799	template<class arg1_type, class arg2_type, class mt_policy>
800	class _signal_base2 : public _signal_base<mt_policy>
801	{
802	public:
803		typedef std::list<_connection_base2<arg1_type, arg2_type, mt_policy> *>
804			connections_list;
805
806		_signal_base2()
807		{
808			;
809		}
810
811		_signal_base2(const _signal_base2<arg1_type, arg2_type, mt_policy>& s)
812			: _signal_base<mt_policy>(s)
813		{
814			lock_block<mt_policy> lock(this);
815			typename connections_list::const_iterator it = s.m_connected_slots.begin();
816			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
817
818			while(it != itEnd)
819			{
820				(*it)->getdest()->signal_connect(this);
821				m_connected_slots.push_back((*it)->clone());
822
823				++it;
824			}
825		}
826
827		void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget)
828		{
829			lock_block<mt_policy> lock(this);
830			typename connections_list::iterator it = m_connected_slots.begin();
831			typename connections_list::iterator itEnd = m_connected_slots.end();
832
833			while(it != itEnd)
834			{
835				if((*it)->getdest() == oldtarget)
836				{
837					m_connected_slots.push_back((*it)->duplicate(newtarget));
838				}
839
840				++it;
841			}
842		}
843
844		~_signal_base2()
845		{
846			disconnect_all();
847		}
848
849		bool is_empty()
850		{
851			lock_block<mt_policy> lock(this);
852			typename connections_list::const_iterator it = m_connected_slots.begin();
853			typename connections_list::const_iterator itEnd = m_connected_slots.end();
854			return it == itEnd;
855		}
856
857		void disconnect_all()
858		{
859			lock_block<mt_policy> lock(this);
860			typename connections_list::const_iterator it = m_connected_slots.begin();
861			typename connections_list::const_iterator itEnd = m_connected_slots.end();
862
863			while(it != itEnd)
864			{
865				(*it)->getdest()->signal_disconnect(this);
866				delete *it;
867
868				++it;
869			}
870
871			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
872		}
873
874#ifdef _DEBUG
875			bool connected(has_slots_interface* pclass)
876		{
877			lock_block<mt_policy> lock(this);
878			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
879			typename connections_list::const_iterator itEnd = m_connected_slots.end();
880			while(it != itEnd)
881			{
882				itNext = it;
883				++itNext;
884				if ((*it)->getdest() == pclass)
885					return true;
886				it = itNext;
887			}
888			return false;
889		}
890#endif
891
892		void disconnect(has_slots_interface* pclass)
893		{
894			lock_block<mt_policy> lock(this);
895			typename connections_list::iterator it = m_connected_slots.begin();
896			typename connections_list::iterator itEnd = m_connected_slots.end();
897
898			while(it != itEnd)
899			{
900				if((*it)->getdest() == pclass)
901				{
902					delete *it;
903					m_connected_slots.erase(it);
904					pclass->signal_disconnect(this);
905					return;
906				}
907
908				++it;
909			}
910		}
911
912		void slot_disconnect(has_slots_interface* pslot)
913		{
914			lock_block<mt_policy> lock(this);
915			typename connections_list::iterator it = m_connected_slots.begin();
916			typename connections_list::iterator itEnd = m_connected_slots.end();
917
918			while(it != itEnd)
919			{
920				typename connections_list::iterator itNext = it;
921				++itNext;
922
923				if((*it)->getdest() == pslot)
924				{
925					delete *it;
926					m_connected_slots.erase(it);
927				}
928
929				it = itNext;
930			}
931		}
932
933	protected:
934		connections_list m_connected_slots;
935	};
936
937	template<class arg1_type, class arg2_type, class arg3_type, class mt_policy>
938	class _signal_base3 : public _signal_base<mt_policy>
939	{
940	public:
941		typedef std::list<_connection_base3<arg1_type, arg2_type, arg3_type, mt_policy> *>
942			connections_list;
943
944		_signal_base3()
945		{
946			;
947		}
948
949		_signal_base3(const _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>& s)
950			: _signal_base<mt_policy>(s)
951		{
952			lock_block<mt_policy> lock(this);
953			typename connections_list::const_iterator it = s.m_connected_slots.begin();
954			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
955
956			while(it != itEnd)
957			{
958				(*it)->getdest()->signal_connect(this);
959				m_connected_slots.push_back((*it)->clone());
960
961				++it;
962			}
963		}
964
965		void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget)
966		{
967			lock_block<mt_policy> lock(this);
968			typename connections_list::iterator it = m_connected_slots.begin();
969			typename connections_list::iterator itEnd = m_connected_slots.end();
970
971			while(it != itEnd)
972			{
973				if((*it)->getdest() == oldtarget)
974				{
975					m_connected_slots.push_back((*it)->duplicate(newtarget));
976				}
977
978				++it;
979			}
980		}
981
982		~_signal_base3()
983		{
984			disconnect_all();
985		}
986
987		bool is_empty()
988		{
989			lock_block<mt_policy> lock(this);
990			typename connections_list::const_iterator it = m_connected_slots.begin();
991			typename connections_list::const_iterator itEnd = m_connected_slots.end();
992			return it == itEnd;
993		}
994
995		void disconnect_all()
996		{
997			lock_block<mt_policy> lock(this);
998			typename connections_list::const_iterator it = m_connected_slots.begin();
999			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1000
1001			while(it != itEnd)
1002			{
1003				(*it)->getdest()->signal_disconnect(this);
1004				delete *it;
1005
1006				++it;
1007			}
1008
1009			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
1010		}
1011
1012#ifdef _DEBUG
1013			bool connected(has_slots_interface* pclass)
1014		{
1015			lock_block<mt_policy> lock(this);
1016			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
1017			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1018			while(it != itEnd)
1019			{
1020				itNext = it;
1021				++itNext;
1022				if ((*it)->getdest() == pclass)
1023					return true;
1024				it = itNext;
1025			}
1026			return false;
1027		}
1028#endif
1029
1030		void disconnect(has_slots_interface* pclass)
1031		{
1032			lock_block<mt_policy> lock(this);
1033			typename connections_list::iterator it = m_connected_slots.begin();
1034			typename connections_list::iterator itEnd = m_connected_slots.end();
1035
1036			while(it != itEnd)
1037			{
1038				if((*it)->getdest() == pclass)
1039				{
1040					delete *it;
1041					m_connected_slots.erase(it);
1042					pclass->signal_disconnect(this);
1043					return;
1044				}
1045
1046				++it;
1047			}
1048		}
1049
1050		void slot_disconnect(has_slots_interface* pslot)
1051		{
1052			lock_block<mt_policy> lock(this);
1053			typename connections_list::iterator it = m_connected_slots.begin();
1054			typename connections_list::iterator itEnd = m_connected_slots.end();
1055
1056			while(it != itEnd)
1057			{
1058				typename connections_list::iterator itNext = it;
1059				++itNext;
1060
1061				if((*it)->getdest() == pslot)
1062				{
1063					delete *it;
1064					m_connected_slots.erase(it);
1065				}
1066
1067				it = itNext;
1068			}
1069		}
1070
1071	protected:
1072		connections_list m_connected_slots;
1073	};
1074
1075	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy>
1076	class _signal_base4 : public _signal_base<mt_policy>
1077	{
1078	public:
1079		typedef std::list<_connection_base4<arg1_type, arg2_type, arg3_type,
1080			arg4_type, mt_policy> *>  connections_list;
1081
1082		_signal_base4()
1083		{
1084			;
1085		}
1086
1087		_signal_base4(const _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>& s)
1088			: _signal_base<mt_policy>(s)
1089		{
1090			lock_block<mt_policy> lock(this);
1091			typename connections_list::const_iterator it = s.m_connected_slots.begin();
1092			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
1093
1094			while(it != itEnd)
1095			{
1096				(*it)->getdest()->signal_connect(this);
1097				m_connected_slots.push_back((*it)->clone());
1098
1099				++it;
1100			}
1101		}
1102
1103		void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget)
1104		{
1105			lock_block<mt_policy> lock(this);
1106			typename connections_list::iterator it = m_connected_slots.begin();
1107			typename connections_list::iterator itEnd = m_connected_slots.end();
1108
1109			while(it != itEnd)
1110			{
1111				if((*it)->getdest() == oldtarget)
1112				{
1113					m_connected_slots.push_back((*it)->duplicate(newtarget));
1114				}
1115
1116				++it;
1117			}
1118		}
1119
1120		~_signal_base4()
1121		{
1122			disconnect_all();
1123		}
1124
1125		bool is_empty()
1126		{
1127			lock_block<mt_policy> lock(this);
1128			typename connections_list::const_iterator it = m_connected_slots.begin();
1129			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1130			return it == itEnd;
1131		}
1132
1133		void disconnect_all()
1134		{
1135			lock_block<mt_policy> lock(this);
1136			typename connections_list::const_iterator it = m_connected_slots.begin();
1137			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1138
1139			while(it != itEnd)
1140			{
1141				(*it)->getdest()->signal_disconnect(this);
1142				delete *it;
1143
1144				++it;
1145			}
1146
1147			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
1148		}
1149
1150#ifdef _DEBUG
1151			bool connected(has_slots_interface* pclass)
1152		{
1153			lock_block<mt_policy> lock(this);
1154			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
1155			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1156			while(it != itEnd)
1157			{
1158				itNext = it;
1159				++itNext;
1160				if ((*it)->getdest() == pclass)
1161					return true;
1162				it = itNext;
1163			}
1164			return false;
1165		}
1166#endif
1167
1168		void disconnect(has_slots_interface* pclass)
1169		{
1170			lock_block<mt_policy> lock(this);
1171			typename connections_list::iterator it = m_connected_slots.begin();
1172			typename connections_list::iterator itEnd = m_connected_slots.end();
1173
1174			while(it != itEnd)
1175			{
1176				if((*it)->getdest() == pclass)
1177				{
1178					delete *it;
1179					m_connected_slots.erase(it);
1180					pclass->signal_disconnect(this);
1181					return;
1182				}
1183
1184				++it;
1185			}
1186		}
1187
1188		void slot_disconnect(has_slots_interface* pslot)
1189		{
1190			lock_block<mt_policy> lock(this);
1191			typename connections_list::iterator it = m_connected_slots.begin();
1192			typename connections_list::iterator itEnd = m_connected_slots.end();
1193
1194			while(it != itEnd)
1195			{
1196				typename connections_list::iterator itNext = it;
1197				++itNext;
1198
1199				if((*it)->getdest() == pslot)
1200				{
1201					delete *it;
1202					m_connected_slots.erase(it);
1203				}
1204
1205				it = itNext;
1206			}
1207		}
1208
1209	protected:
1210		connections_list m_connected_slots;
1211	};
1212
1213	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
1214	class arg5_type, class mt_policy>
1215	class _signal_base5 : public _signal_base<mt_policy>
1216	{
1217	public:
1218		typedef std::list<_connection_base5<arg1_type, arg2_type, arg3_type,
1219			arg4_type, arg5_type, mt_policy> *>  connections_list;
1220
1221		_signal_base5()
1222		{
1223			;
1224		}
1225
1226		_signal_base5(const _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type,
1227			arg5_type, mt_policy>& s)
1228			: _signal_base<mt_policy>(s)
1229		{
1230			lock_block<mt_policy> lock(this);
1231			typename connections_list::const_iterator it = s.m_connected_slots.begin();
1232			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
1233
1234			while(it != itEnd)
1235			{
1236				(*it)->getdest()->signal_connect(this);
1237				m_connected_slots.push_back((*it)->clone());
1238
1239				++it;
1240			}
1241		}
1242
1243		void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget)
1244		{
1245			lock_block<mt_policy> lock(this);
1246			typename connections_list::iterator it = m_connected_slots.begin();
1247			typename connections_list::iterator itEnd = m_connected_slots.end();
1248
1249			while(it != itEnd)
1250			{
1251				if((*it)->getdest() == oldtarget)
1252				{
1253					m_connected_slots.push_back((*it)->duplicate(newtarget));
1254				}
1255
1256				++it;
1257			}
1258		}
1259
1260		~_signal_base5()
1261		{
1262			disconnect_all();
1263		}
1264
1265		bool is_empty()
1266		{
1267			lock_block<mt_policy> lock(this);
1268			typename connections_list::const_iterator it = m_connected_slots.begin();
1269			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1270			return it == itEnd;
1271		}
1272
1273		void disconnect_all()
1274		{
1275			lock_block<mt_policy> lock(this);
1276			typename connections_list::const_iterator it = m_connected_slots.begin();
1277			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1278
1279			while(it != itEnd)
1280			{
1281				(*it)->getdest()->signal_disconnect(this);
1282				delete *it;
1283
1284				++it;
1285			}
1286
1287			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
1288		}
1289
1290#ifdef _DEBUG
1291			bool connected(has_slots_interface* pclass)
1292		{
1293			lock_block<mt_policy> lock(this);
1294			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
1295			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1296			while(it != itEnd)
1297			{
1298				itNext = it;
1299				++itNext;
1300				if ((*it)->getdest() == pclass)
1301					return true;
1302				it = itNext;
1303			}
1304			return false;
1305		}
1306#endif
1307
1308		void disconnect(has_slots_interface* pclass)
1309		{
1310			lock_block<mt_policy> lock(this);
1311			typename connections_list::iterator it = m_connected_slots.begin();
1312			typename connections_list::iterator itEnd = m_connected_slots.end();
1313
1314			while(it != itEnd)
1315			{
1316				if((*it)->getdest() == pclass)
1317				{
1318					delete *it;
1319					m_connected_slots.erase(it);
1320					pclass->signal_disconnect(this);
1321					return;
1322				}
1323
1324				++it;
1325			}
1326		}
1327
1328		void slot_disconnect(has_slots_interface* pslot)
1329		{
1330			lock_block<mt_policy> lock(this);
1331			typename connections_list::iterator it = m_connected_slots.begin();
1332			typename connections_list::iterator itEnd = m_connected_slots.end();
1333
1334			while(it != itEnd)
1335			{
1336				typename connections_list::iterator itNext = it;
1337				++itNext;
1338
1339				if((*it)->getdest() == pslot)
1340				{
1341					delete *it;
1342					m_connected_slots.erase(it);
1343				}
1344
1345				it = itNext;
1346			}
1347		}
1348
1349	protected:
1350		connections_list m_connected_slots;
1351	};
1352
1353	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
1354	class arg5_type, class arg6_type, class mt_policy>
1355	class _signal_base6 : public _signal_base<mt_policy>
1356	{
1357	public:
1358		typedef std::list<_connection_base6<arg1_type, arg2_type, arg3_type,
1359			arg4_type, arg5_type, arg6_type, mt_policy> *>  connections_list;
1360
1361		_signal_base6()
1362		{
1363			;
1364		}
1365
1366		_signal_base6(const _signal_base6<arg1_type, arg2_type, arg3_type, arg4_type,
1367			arg5_type, arg6_type, mt_policy>& s)
1368			: _signal_base<mt_policy>(s)
1369		{
1370			lock_block<mt_policy> lock(this);
1371			typename connections_list::const_iterator it = s.m_connected_slots.begin();
1372			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
1373
1374			while(it != itEnd)
1375			{
1376				(*it)->getdest()->signal_connect(this);
1377				m_connected_slots.push_back((*it)->clone());
1378
1379				++it;
1380			}
1381		}
1382
1383		void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget)
1384		{
1385			lock_block<mt_policy> lock(this);
1386			typename connections_list::iterator it = m_connected_slots.begin();
1387			typename connections_list::iterator itEnd = m_connected_slots.end();
1388
1389			while(it != itEnd)
1390			{
1391				if((*it)->getdest() == oldtarget)
1392				{
1393					m_connected_slots.push_back((*it)->duplicate(newtarget));
1394				}
1395
1396				++it;
1397			}
1398		}
1399
1400		~_signal_base6()
1401		{
1402			disconnect_all();
1403		}
1404
1405		bool is_empty()
1406		{
1407			lock_block<mt_policy> lock(this);
1408			typename connections_list::const_iterator it = m_connected_slots.begin();
1409			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1410			return it == itEnd;
1411		}
1412
1413		void disconnect_all()
1414		{
1415			lock_block<mt_policy> lock(this);
1416			typename connections_list::const_iterator it = m_connected_slots.begin();
1417			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1418
1419			while(it != itEnd)
1420			{
1421				(*it)->getdest()->signal_disconnect(this);
1422				delete *it;
1423
1424				++it;
1425			}
1426
1427			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
1428		}
1429
1430#ifdef _DEBUG
1431			bool connected(has_slots_interface* pclass)
1432		{
1433			lock_block<mt_policy> lock(this);
1434			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
1435			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1436			while(it != itEnd)
1437			{
1438				itNext = it;
1439				++itNext;
1440				if ((*it)->getdest() == pclass)
1441					return true;
1442				it = itNext;
1443			}
1444			return false;
1445		}
1446#endif
1447
1448		void disconnect(has_slots_interface* pclass)
1449		{
1450			lock_block<mt_policy> lock(this);
1451			typename connections_list::iterator it = m_connected_slots.begin();
1452			typename connections_list::iterator itEnd = m_connected_slots.end();
1453
1454			while(it != itEnd)
1455			{
1456				if((*it)->getdest() == pclass)
1457				{
1458					delete *it;
1459					m_connected_slots.erase(it);
1460					pclass->signal_disconnect(this);
1461					return;
1462				}
1463
1464				++it;
1465			}
1466		}
1467
1468		void slot_disconnect(has_slots_interface* pslot)
1469		{
1470			lock_block<mt_policy> lock(this);
1471			typename connections_list::iterator it = m_connected_slots.begin();
1472			typename connections_list::iterator itEnd = m_connected_slots.end();
1473
1474			while(it != itEnd)
1475			{
1476				typename connections_list::iterator itNext = it;
1477				++itNext;
1478
1479				if((*it)->getdest() == pslot)
1480				{
1481					delete *it;
1482					m_connected_slots.erase(it);
1483				}
1484
1485				it = itNext;
1486			}
1487		}
1488
1489	protected:
1490		connections_list m_connected_slots;
1491	};
1492
1493	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
1494	class arg5_type, class arg6_type, class arg7_type, class mt_policy>
1495	class _signal_base7 : public _signal_base<mt_policy>
1496	{
1497	public:
1498		typedef std::list<_connection_base7<arg1_type, arg2_type, arg3_type,
1499			arg4_type, arg5_type, arg6_type, arg7_type, mt_policy> *>  connections_list;
1500
1501		_signal_base7()
1502		{
1503			;
1504		}
1505
1506		_signal_base7(const _signal_base7<arg1_type, arg2_type, arg3_type, arg4_type,
1507			arg5_type, arg6_type, arg7_type, mt_policy>& s)
1508			: _signal_base<mt_policy>(s)
1509		{
1510			lock_block<mt_policy> lock(this);
1511			typename connections_list::const_iterator it = s.m_connected_slots.begin();
1512			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
1513
1514			while(it != itEnd)
1515			{
1516				(*it)->getdest()->signal_connect(this);
1517				m_connected_slots.push_back((*it)->clone());
1518
1519				++it;
1520			}
1521		}
1522
1523		void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget)
1524		{
1525			lock_block<mt_policy> lock(this);
1526			typename connections_list::iterator it = m_connected_slots.begin();
1527			typename connections_list::iterator itEnd = m_connected_slots.end();
1528
1529			while(it != itEnd)
1530			{
1531				if((*it)->getdest() == oldtarget)
1532				{
1533					m_connected_slots.push_back((*it)->duplicate(newtarget));
1534				}
1535
1536				++it;
1537			}
1538		}
1539
1540		~_signal_base7()
1541		{
1542			disconnect_all();
1543		}
1544
1545		bool is_empty()
1546		{
1547			lock_block<mt_policy> lock(this);
1548			typename connections_list::const_iterator it = m_connected_slots.begin();
1549			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1550			return it == itEnd;
1551		}
1552
1553		void disconnect_all()
1554		{
1555			lock_block<mt_policy> lock(this);
1556			typename connections_list::const_iterator it = m_connected_slots.begin();
1557			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1558
1559			while(it != itEnd)
1560			{
1561				(*it)->getdest()->signal_disconnect(this);
1562				delete *it;
1563
1564				++it;
1565			}
1566
1567			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
1568		}
1569
1570#ifdef _DEBUG
1571			bool connected(has_slots_interface* pclass)
1572		{
1573			lock_block<mt_policy> lock(this);
1574			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
1575			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1576			while(it != itEnd)
1577			{
1578				itNext = it;
1579				++itNext;
1580				if ((*it)->getdest() == pclass)
1581					return true;
1582				it = itNext;
1583			}
1584			return false;
1585		}
1586#endif
1587
1588		void disconnect(has_slots_interface* pclass)
1589		{
1590			lock_block<mt_policy> lock(this);
1591			typename connections_list::iterator it = m_connected_slots.begin();
1592			typename connections_list::iterator itEnd = m_connected_slots.end();
1593
1594			while(it != itEnd)
1595			{
1596				if((*it)->getdest() == pclass)
1597				{
1598					delete *it;
1599					m_connected_slots.erase(it);
1600					pclass->signal_disconnect(this);
1601					return;
1602				}
1603
1604				++it;
1605			}
1606		}
1607
1608		void slot_disconnect(has_slots_interface* pslot)
1609		{
1610			lock_block<mt_policy> lock(this);
1611			typename connections_list::iterator it = m_connected_slots.begin();
1612			typename connections_list::iterator itEnd = m_connected_slots.end();
1613
1614			while(it != itEnd)
1615			{
1616				typename connections_list::iterator itNext = it;
1617				++itNext;
1618
1619				if((*it)->getdest() == pslot)
1620				{
1621					delete *it;
1622					m_connected_slots.erase(it);
1623				}
1624
1625				it = itNext;
1626			}
1627		}
1628
1629	protected:
1630		connections_list m_connected_slots;
1631	};
1632
1633	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
1634	class arg5_type, class arg6_type, class arg7_type, class arg8_type, class mt_policy>
1635	class _signal_base8 : public _signal_base<mt_policy>
1636	{
1637	public:
1638		typedef std::list<_connection_base8<arg1_type, arg2_type, arg3_type,
1639			arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy> *>
1640			connections_list;
1641
1642		_signal_base8()
1643		{
1644			;
1645		}
1646
1647		_signal_base8(const _signal_base8<arg1_type, arg2_type, arg3_type, arg4_type,
1648			arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>& s)
1649			: _signal_base<mt_policy>(s)
1650		{
1651			lock_block<mt_policy> lock(this);
1652			typename connections_list::const_iterator it = s.m_connected_slots.begin();
1653			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
1654
1655			while(it != itEnd)
1656			{
1657				(*it)->getdest()->signal_connect(this);
1658				m_connected_slots.push_back((*it)->clone());
1659
1660				++it;
1661			}
1662		}
1663
1664		void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget)
1665		{
1666			lock_block<mt_policy> lock(this);
1667			typename connections_list::iterator it = m_connected_slots.begin();
1668			typename connections_list::iterator itEnd = m_connected_slots.end();
1669
1670			while(it != itEnd)
1671			{
1672				if((*it)->getdest() == oldtarget)
1673				{
1674					m_connected_slots.push_back((*it)->duplicate(newtarget));
1675				}
1676
1677				++it;
1678			}
1679		}
1680
1681		~_signal_base8()
1682		{
1683			disconnect_all();
1684		}
1685
1686		bool is_empty()
1687		{
1688			lock_block<mt_policy> lock(this);
1689			typename connections_list::const_iterator it = m_connected_slots.begin();
1690			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1691			return it == itEnd;
1692		}
1693
1694		void disconnect_all()
1695		{
1696			lock_block<mt_policy> lock(this);
1697			typename connections_list::const_iterator it = m_connected_slots.begin();
1698			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1699
1700			while(it != itEnd)
1701			{
1702				(*it)->getdest()->signal_disconnect(this);
1703				delete *it;
1704
1705				++it;
1706			}
1707
1708			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
1709		}
1710
1711#ifdef _DEBUG
1712			bool connected(has_slots_interface* pclass)
1713		{
1714			lock_block<mt_policy> lock(this);
1715			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
1716			typename connections_list::const_iterator itEnd = m_connected_slots.end();
1717			while(it != itEnd)
1718			{
1719				itNext = it;
1720				++itNext;
1721				if ((*it)->getdest() == pclass)
1722					return true;
1723				it = itNext;
1724			}
1725			return false;
1726		}
1727#endif
1728
1729		void disconnect(has_slots_interface* pclass)
1730		{
1731			lock_block<mt_policy> lock(this);
1732			typename connections_list::iterator it = m_connected_slots.begin();
1733			typename connections_list::iterator itEnd = m_connected_slots.end();
1734
1735			while(it != itEnd)
1736			{
1737				if((*it)->getdest() == pclass)
1738				{
1739					delete *it;
1740					m_connected_slots.erase(it);
1741					pclass->signal_disconnect(this);
1742					return;
1743				}
1744
1745				++it;
1746			}
1747		}
1748
1749		void slot_disconnect(has_slots_interface* pslot)
1750		{
1751			lock_block<mt_policy> lock(this);
1752			typename connections_list::iterator it = m_connected_slots.begin();
1753			typename connections_list::iterator itEnd = m_connected_slots.end();
1754
1755			while(it != itEnd)
1756			{
1757				typename connections_list::iterator itNext = it;
1758				++itNext;
1759
1760				if((*it)->getdest() == pslot)
1761				{
1762					delete *it;
1763					m_connected_slots.erase(it);
1764				}
1765
1766				it = itNext;
1767			}
1768		}
1769
1770	protected:
1771		connections_list m_connected_slots;
1772	};
1773
1774
1775	template<class dest_type, class mt_policy>
1776	class _connection0 : public _connection_base0<mt_policy>
1777	{
1778	public:
1779		_connection0()
1780		{
1781			m_pobject = NULL;
1782			m_pmemfun = NULL;
1783		}
1784
1785		_connection0(dest_type* pobject, void (dest_type::*pmemfun)())
1786		{
1787			m_pobject = pobject;
1788			m_pmemfun = pmemfun;
1789		}
1790
1791		virtual ~_connection0()
1792		{
1793                }
1794
1795		virtual _connection_base0<mt_policy>* clone()
1796		{
1797			return new _connection0<dest_type, mt_policy>(*this);
1798		}
1799
1800		virtual _connection_base0<mt_policy>* duplicate(has_slots_interface* pnewdest)
1801		{
1802			return new _connection0<dest_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
1803		}
1804
1805		virtual void emit()
1806		{
1807			(m_pobject->*m_pmemfun)();
1808		}
1809
1810		virtual has_slots_interface* getdest() const
1811		{
1812			return m_pobject;
1813		}
1814
1815	private:
1816		dest_type* m_pobject;
1817		void (dest_type::* m_pmemfun)();
1818	};
1819
1820	template<class dest_type, class arg1_type, class mt_policy>
1821	class _connection1 : public _connection_base1<arg1_type, mt_policy>
1822	{
1823	public:
1824		_connection1()
1825		{
1826			m_pobject = NULL;
1827			m_pmemfun = NULL;
1828		}
1829
1830		_connection1(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type))
1831		{
1832			m_pobject = pobject;
1833			m_pmemfun = pmemfun;
1834		}
1835
1836		virtual ~_connection1()
1837		{
1838                }
1839
1840		virtual _connection_base1<arg1_type, mt_policy>* clone()
1841		{
1842			return new _connection1<dest_type, arg1_type, mt_policy>(*this);
1843		}
1844
1845		virtual _connection_base1<arg1_type, mt_policy>* duplicate(has_slots_interface* pnewdest)
1846		{
1847			return new _connection1<dest_type, arg1_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
1848		}
1849
1850		virtual void emit(arg1_type a1)
1851		{
1852			(m_pobject->*m_pmemfun)(a1);
1853		}
1854
1855		virtual has_slots_interface* getdest() const
1856		{
1857			return m_pobject;
1858		}
1859
1860	private:
1861		dest_type* m_pobject;
1862		void (dest_type::* m_pmemfun)(arg1_type);
1863	};
1864
1865	template<class dest_type, class arg1_type, class arg2_type, class mt_policy>
1866	class _connection2 : public _connection_base2<arg1_type, arg2_type, mt_policy>
1867	{
1868	public:
1869		_connection2()
1870		{
1871			m_pobject = NULL;
1872			m_pmemfun = NULL;
1873		}
1874
1875		_connection2(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,
1876			arg2_type))
1877		{
1878			m_pobject = pobject;
1879			m_pmemfun = pmemfun;
1880		}
1881
1882		virtual ~_connection2()
1883		{
1884                }
1885
1886		virtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone()
1887		{
1888			return new _connection2<dest_type, arg1_type, arg2_type, mt_policy>(*this);
1889		}
1890
1891		virtual _connection_base2<arg1_type, arg2_type, mt_policy>* duplicate(has_slots_interface* pnewdest)
1892		{
1893			return new _connection2<dest_type, arg1_type, arg2_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
1894		}
1895
1896		virtual void emit(arg1_type a1, arg2_type a2)
1897		{
1898			(m_pobject->*m_pmemfun)(a1, a2);
1899		}
1900
1901		virtual has_slots_interface* getdest() const
1902		{
1903			return m_pobject;
1904		}
1905
1906	private:
1907		dest_type* m_pobject;
1908		void (dest_type::* m_pmemfun)(arg1_type, arg2_type);
1909	};
1910
1911	template<class dest_type, class arg1_type, class arg2_type, class arg3_type, class mt_policy>
1912	class _connection3 : public _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>
1913	{
1914	public:
1915		_connection3()
1916		{
1917			m_pobject = NULL;
1918			m_pmemfun = NULL;
1919		}
1920
1921		_connection3(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,
1922			arg2_type, arg3_type))
1923		{
1924			m_pobject = pobject;
1925			m_pmemfun = pmemfun;
1926		}
1927
1928		virtual ~_connection3()
1929		{
1930                }
1931
1932		virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* clone()
1933		{
1934			return new _connection3<dest_type, arg1_type, arg2_type, arg3_type, mt_policy>(*this);
1935		}
1936
1937		virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* duplicate(has_slots_interface* pnewdest)
1938		{
1939			return new _connection3<dest_type, arg1_type, arg2_type, arg3_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
1940		}
1941
1942		virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3)
1943		{
1944			(m_pobject->*m_pmemfun)(a1, a2, a3);
1945		}
1946
1947		virtual has_slots_interface* getdest() const
1948		{
1949			return m_pobject;
1950		}
1951
1952	private:
1953		dest_type* m_pobject;
1954		void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type);
1955	};
1956
1957	template<class dest_type, class arg1_type, class arg2_type, class arg3_type,
1958	class arg4_type, class mt_policy>
1959	class _connection4 : public _connection_base4<arg1_type, arg2_type,
1960		arg3_type, arg4_type, mt_policy>
1961	{
1962	public:
1963		_connection4()
1964		{
1965			m_pobject = NULL;
1966			m_pmemfun = NULL;
1967		}
1968
1969		_connection4(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,
1970			arg2_type, arg3_type, arg4_type))
1971		{
1972			m_pobject = pobject;
1973			m_pmemfun = pmemfun;
1974		}
1975
1976		virtual ~_connection4()
1977		{
1978                }
1979
1980		virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* clone()
1981		{
1982			return new _connection4<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>(*this);
1983		}
1984
1985		virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* duplicate(has_slots_interface* pnewdest)
1986		{
1987			return new _connection4<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
1988		}
1989
1990		virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3,
1991			arg4_type a4)
1992		{
1993			(m_pobject->*m_pmemfun)(a1, a2, a3, a4);
1994		}
1995
1996		virtual has_slots_interface* getdest() const
1997		{
1998			return m_pobject;
1999		}
2000
2001	private:
2002		dest_type* m_pobject;
2003		void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type,
2004			arg4_type);
2005	};
2006
2007	template<class dest_type, class arg1_type, class arg2_type, class arg3_type,
2008	class arg4_type, class arg5_type, class mt_policy>
2009	class _connection5 : public _connection_base5<arg1_type, arg2_type,
2010		arg3_type, arg4_type, arg5_type, mt_policy>
2011	{
2012	public:
2013		_connection5()
2014		{
2015			m_pobject = NULL;
2016			m_pmemfun = NULL;
2017		}
2018
2019		_connection5(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,
2020			arg2_type, arg3_type, arg4_type, arg5_type))
2021		{
2022			m_pobject = pobject;
2023			m_pmemfun = pmemfun;
2024		}
2025
2026		virtual ~_connection5()
2027		{
2028                }
2029
2030		virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,
2031			arg5_type, mt_policy>* clone()
2032		{
2033			return new _connection5<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,
2034				arg5_type, mt_policy>(*this);
2035		}
2036
2037		virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,
2038			arg5_type, mt_policy>* duplicate(has_slots_interface* pnewdest)
2039		{
2040			return new _connection5<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,
2041				arg5_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
2042		}
2043
2044		virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
2045			arg5_type a5)
2046		{
2047			(m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5);
2048		}
2049
2050		virtual has_slots_interface* getdest() const
2051		{
2052			return m_pobject;
2053		}
2054
2055	private:
2056		dest_type* m_pobject;
2057		void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,
2058			arg5_type);
2059	};
2060
2061	template<class dest_type, class arg1_type, class arg2_type, class arg3_type,
2062	class arg4_type, class arg5_type, class arg6_type, class mt_policy>
2063	class _connection6 : public _connection_base6<arg1_type, arg2_type,
2064		arg3_type, arg4_type, arg5_type, arg6_type, mt_policy>
2065	{
2066	public:
2067		_connection6()
2068		{
2069			m_pobject = NULL;
2070			m_pmemfun = NULL;
2071		}
2072
2073		_connection6(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,
2074			arg2_type, arg3_type, arg4_type, arg5_type, arg6_type))
2075		{
2076			m_pobject = pobject;
2077			m_pmemfun = pmemfun;
2078		}
2079
2080		virtual ~_connection6()
2081		{
2082                }
2083
2084		virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,
2085			arg5_type, arg6_type, mt_policy>* clone()
2086		{
2087			return new _connection6<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,
2088				arg5_type, arg6_type, mt_policy>(*this);
2089		}
2090
2091		virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,
2092			arg5_type, arg6_type, mt_policy>* duplicate(has_slots_interface* pnewdest)
2093		{
2094			return new _connection6<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,
2095				arg5_type, arg6_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
2096		}
2097
2098		virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
2099			arg5_type a5, arg6_type a6)
2100		{
2101			(m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6);
2102		}
2103
2104		virtual has_slots_interface* getdest() const
2105		{
2106			return m_pobject;
2107		}
2108
2109	private:
2110		dest_type* m_pobject;
2111		void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,
2112			arg5_type, arg6_type);
2113	};
2114
2115	template<class dest_type, class arg1_type, class arg2_type, class arg3_type,
2116	class arg4_type, class arg5_type, class arg6_type, class arg7_type, class mt_policy>
2117	class _connection7 : public _connection_base7<arg1_type, arg2_type,
2118		arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>
2119	{
2120	public:
2121		_connection7()
2122		{
2123			m_pobject = NULL;
2124			m_pmemfun = NULL;
2125		}
2126
2127		_connection7(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,
2128			arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type))
2129		{
2130			m_pobject = pobject;
2131			m_pmemfun = pmemfun;
2132		}
2133
2134		virtual ~_connection7()
2135		{
2136                }
2137
2138		virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,
2139			arg5_type, arg6_type, arg7_type, mt_policy>* clone()
2140		{
2141			return new _connection7<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,
2142				arg5_type, arg6_type, arg7_type, mt_policy>(*this);
2143		}
2144
2145		virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,
2146			arg5_type, arg6_type, arg7_type, mt_policy>* duplicate(has_slots_interface* pnewdest)
2147		{
2148			return new _connection7<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,
2149				arg5_type, arg6_type, arg7_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
2150		}
2151
2152		virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
2153			arg5_type a5, arg6_type a6, arg7_type a7)
2154		{
2155			(m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7);
2156		}
2157
2158		virtual has_slots_interface* getdest() const
2159		{
2160			return m_pobject;
2161		}
2162
2163	private:
2164		dest_type* m_pobject;
2165		void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,
2166			arg5_type, arg6_type, arg7_type);
2167	};
2168
2169	template<class dest_type, class arg1_type, class arg2_type, class arg3_type,
2170	class arg4_type, class arg5_type, class arg6_type, class arg7_type,
2171	class arg8_type, class mt_policy>
2172	class _connection8 : public _connection_base8<arg1_type, arg2_type,
2173		arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>
2174	{
2175	public:
2176		_connection8()
2177		{
2178			m_pobject = NULL;
2179			m_pmemfun = NULL;
2180		}
2181
2182		_connection8(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,
2183			arg2_type, arg3_type, arg4_type, arg5_type, arg6_type,
2184			arg7_type, arg8_type))
2185		{
2186			m_pobject = pobject;
2187			m_pmemfun = pmemfun;
2188		}
2189
2190		virtual ~_connection8()
2191		{
2192                }
2193
2194		virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,
2195			arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* clone()
2196		{
2197			return new _connection8<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,
2198				arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>(*this);
2199		}
2200
2201		virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,
2202			arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* duplicate(has_slots_interface* pnewdest)
2203		{
2204			return new _connection8<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,
2205				arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
2206		}
2207
2208		virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
2209			arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8)
2210		{
2211			(m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7, a8);
2212		}
2213
2214		virtual has_slots_interface* getdest() const
2215		{
2216			return m_pobject;
2217		}
2218
2219	private:
2220		dest_type* m_pobject;
2221		void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,
2222			arg5_type, arg6_type, arg7_type, arg8_type);
2223	};
2224
2225	template<class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
2226	class signal0 : public _signal_base0<mt_policy>
2227	{
2228	public:
2229		typedef _signal_base0<mt_policy> base;
2230		typedef typename base::connections_list connections_list;
2231		using base::m_connected_slots;
2232
2233		signal0()
2234		{
2235			;
2236		}
2237
2238		signal0(const signal0<mt_policy>& s)
2239			: _signal_base0<mt_policy>(s)
2240		{
2241			;
2242		}
2243
2244		template<class desttype>
2245			void connect(desttype* pclass, void (desttype::*pmemfun)())
2246		{
2247			lock_block<mt_policy> lock(this);
2248			_connection0<desttype, mt_policy>* conn =
2249				new _connection0<desttype, mt_policy>(pclass, pmemfun);
2250			m_connected_slots.push_back(conn);
2251			pclass->signal_connect(this);
2252		}
2253
2254		void emit()
2255		{
2256			lock_block<mt_policy> lock(this);
2257			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2258			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2259
2260			while(it != itEnd)
2261			{
2262				itNext = it;
2263				++itNext;
2264
2265				(*it)->emit();
2266
2267				it = itNext;
2268			}
2269		}
2270
2271		void operator()()
2272		{
2273			lock_block<mt_policy> lock(this);
2274			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2275			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2276
2277			while(it != itEnd)
2278			{
2279				itNext = it;
2280				++itNext;
2281
2282				(*it)->emit();
2283
2284				it = itNext;
2285			}
2286		}
2287	};
2288
2289	template<class arg1_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
2290	class signal1 : public _signal_base1<arg1_type, mt_policy>
2291	{
2292	public:
2293		typedef _signal_base1<arg1_type, mt_policy> base;
2294		typedef typename base::connections_list connections_list;
2295		using base::m_connected_slots;
2296
2297		signal1()
2298		{
2299			;
2300		}
2301
2302		signal1(const signal1<arg1_type, mt_policy>& s)
2303			: _signal_base1<arg1_type, mt_policy>(s)
2304		{
2305			;
2306		}
2307
2308		template<class desttype>
2309			void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type))
2310		{
2311			lock_block<mt_policy> lock(this);
2312			_connection1<desttype, arg1_type, mt_policy>* conn =
2313				new _connection1<desttype, arg1_type, mt_policy>(pclass, pmemfun);
2314			m_connected_slots.push_back(conn);
2315			pclass->signal_connect(this);
2316		}
2317
2318		void emit(arg1_type a1)
2319		{
2320			lock_block<mt_policy> lock(this);
2321			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2322			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2323
2324			while(it != itEnd)
2325			{
2326				itNext = it;
2327				++itNext;
2328
2329				(*it)->emit(a1);
2330
2331				it = itNext;
2332			}
2333		}
2334
2335		void operator()(arg1_type a1)
2336		{
2337			lock_block<mt_policy> lock(this);
2338			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2339			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2340
2341			while(it != itEnd)
2342			{
2343				itNext = it;
2344				++itNext;
2345
2346				(*it)->emit(a1);
2347
2348				it = itNext;
2349			}
2350		}
2351	};
2352
2353	template<class arg1_type, class arg2_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
2354	class signal2 : public _signal_base2<arg1_type, arg2_type, mt_policy>
2355	{
2356	public:
2357		typedef _signal_base2<arg1_type, arg2_type, mt_policy> base;
2358		typedef typename base::connections_list connections_list;
2359		using base::m_connected_slots;
2360
2361		signal2()
2362		{
2363			;
2364		}
2365
2366		signal2(const signal2<arg1_type, arg2_type, mt_policy>& s)
2367			: _signal_base2<arg1_type, arg2_type, mt_policy>(s)
2368		{
2369			;
2370		}
2371
2372		template<class desttype>
2373			void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
2374			arg2_type))
2375		{
2376			lock_block<mt_policy> lock(this);
2377			_connection2<desttype, arg1_type, arg2_type, mt_policy>* conn = new
2378				_connection2<desttype, arg1_type, arg2_type, mt_policy>(pclass, pmemfun);
2379			m_connected_slots.push_back(conn);
2380			pclass->signal_connect(this);
2381		}
2382
2383		void emit(arg1_type a1, arg2_type a2)
2384		{
2385			lock_block<mt_policy> lock(this);
2386			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2387			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2388
2389			while(it != itEnd)
2390			{
2391				itNext = it;
2392				++itNext;
2393
2394				(*it)->emit(a1, a2);
2395
2396				it = itNext;
2397			}
2398		}
2399
2400		void operator()(arg1_type a1, arg2_type a2)
2401		{
2402			lock_block<mt_policy> lock(this);
2403			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2404			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2405
2406			while(it != itEnd)
2407			{
2408				itNext = it;
2409				++itNext;
2410
2411				(*it)->emit(a1, a2);
2412
2413				it = itNext;
2414			}
2415		}
2416	};
2417
2418	template<class arg1_type, class arg2_type, class arg3_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
2419	class signal3 : public _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>
2420	{
2421	public:
2422		typedef _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy> base;
2423		typedef typename base::connections_list connections_list;
2424		using base::m_connected_slots;
2425
2426		signal3()
2427		{
2428			;
2429		}
2430
2431		signal3(const signal3<arg1_type, arg2_type, arg3_type, mt_policy>& s)
2432			: _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>(s)
2433		{
2434			;
2435		}
2436
2437		template<class desttype>
2438			void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
2439			arg2_type, arg3_type))
2440		{
2441			lock_block<mt_policy> lock(this);
2442			_connection3<desttype, arg1_type, arg2_type, arg3_type, mt_policy>* conn =
2443				new _connection3<desttype, arg1_type, arg2_type, arg3_type, mt_policy>(pclass,
2444				pmemfun);
2445			m_connected_slots.push_back(conn);
2446			pclass->signal_connect(this);
2447		}
2448
2449		void emit(arg1_type a1, arg2_type a2, arg3_type a3)
2450		{
2451			lock_block<mt_policy> lock(this);
2452			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2453			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2454
2455			while(it != itEnd)
2456			{
2457				itNext = it;
2458				++itNext;
2459
2460				(*it)->emit(a1, a2, a3);
2461
2462				it = itNext;
2463			}
2464		}
2465
2466		void operator()(arg1_type a1, arg2_type a2, arg3_type a3)
2467		{
2468			lock_block<mt_policy> lock(this);
2469			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2470			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2471
2472			while(it != itEnd)
2473			{
2474				itNext = it;
2475				++itNext;
2476
2477				(*it)->emit(a1, a2, a3);
2478
2479				it = itNext;
2480			}
2481		}
2482	};
2483
2484	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
2485	class signal4 : public _signal_base4<arg1_type, arg2_type, arg3_type,
2486		arg4_type, mt_policy>
2487	{
2488	public:
2489		typedef _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy> base;
2490		typedef typename base::connections_list connections_list;
2491		using base::m_connected_slots;
2492
2493		signal4()
2494		{
2495			;
2496		}
2497
2498		signal4(const signal4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>& s)
2499			: _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>(s)
2500		{
2501			;
2502		}
2503
2504		template<class desttype>
2505			void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
2506			arg2_type, arg3_type, arg4_type))
2507		{
2508			lock_block<mt_policy> lock(this);
2509			_connection4<desttype, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>*
2510				conn = new _connection4<desttype, arg1_type, arg2_type, arg3_type,
2511				arg4_type, mt_policy>(pclass, pmemfun);
2512			m_connected_slots.push_back(conn);
2513			pclass->signal_connect(this);
2514		}
2515
2516		void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4)
2517		{
2518			lock_block<mt_policy> lock(this);
2519			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2520			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2521
2522			while(it != itEnd)
2523			{
2524				itNext = it;
2525				++itNext;
2526
2527				(*it)->emit(a1, a2, a3, a4);
2528
2529				it = itNext;
2530			}
2531		}
2532
2533		void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4)
2534		{
2535			lock_block<mt_policy> lock(this);
2536			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2537			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2538
2539			while(it != itEnd)
2540			{
2541				itNext = it;
2542				++itNext;
2543
2544				(*it)->emit(a1, a2, a3, a4);
2545
2546				it = itNext;
2547			}
2548		}
2549	};
2550
2551	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
2552	class arg5_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
2553	class signal5 : public _signal_base5<arg1_type, arg2_type, arg3_type,
2554		arg4_type, arg5_type, mt_policy>
2555	{
2556	public:
2557		typedef _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, mt_policy> base;
2558		typedef typename base::connections_list connections_list;
2559		using base::m_connected_slots;
2560
2561		signal5()
2562		{
2563			;
2564		}
2565
2566		signal5(const signal5<arg1_type, arg2_type, arg3_type, arg4_type,
2567			arg5_type, mt_policy>& s)
2568			: _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type,
2569			arg5_type, mt_policy>(s)
2570		{
2571			;
2572		}
2573
2574		template<class desttype>
2575			void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
2576			arg2_type, arg3_type, arg4_type, arg5_type))
2577		{
2578			lock_block<mt_policy> lock(this);
2579			_connection5<desttype, arg1_type, arg2_type, arg3_type, arg4_type,
2580				arg5_type, mt_policy>* conn = new _connection5<desttype, arg1_type, arg2_type,
2581				arg3_type, arg4_type, arg5_type, mt_policy>(pclass, pmemfun);
2582			m_connected_slots.push_back(conn);
2583			pclass->signal_connect(this);
2584		}
2585
2586		void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
2587			arg5_type a5)
2588		{
2589			lock_block<mt_policy> lock(this);
2590			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2591			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2592
2593			while(it != itEnd)
2594			{
2595				itNext = it;
2596				++itNext;
2597
2598				(*it)->emit(a1, a2, a3, a4, a5);
2599
2600				it = itNext;
2601			}
2602		}
2603
2604		void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
2605			arg5_type a5)
2606		{
2607			lock_block<mt_policy> lock(this);
2608			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2609			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2610
2611			while(it != itEnd)
2612			{
2613				itNext = it;
2614				++itNext;
2615
2616				(*it)->emit(a1, a2, a3, a4, a5);
2617
2618				it = itNext;
2619			}
2620		}
2621	};
2622
2623
2624	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
2625	class arg5_type, class arg6_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
2626	class signal6 : public _signal_base6<arg1_type, arg2_type, arg3_type,
2627		arg4_type, arg5_type, arg6_type, mt_policy>
2628	{
2629	public:
2630		typedef _signal_base6<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, mt_policy> base;
2631		typedef typename base::connections_list connections_list;
2632		using base::m_connected_slots;
2633
2634		signal6()
2635		{
2636			;
2637		}
2638
2639		signal6(const signal6<arg1_type, arg2_type, arg3_type, arg4_type,
2640			arg5_type, arg6_type, mt_policy>& s)
2641			: _signal_base6<arg1_type, arg2_type, arg3_type, arg4_type,
2642			arg5_type, arg6_type, mt_policy>(s)
2643		{
2644			;
2645		}
2646
2647		template<class desttype>
2648			void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
2649			arg2_type, arg3_type, arg4_type, arg5_type, arg6_type))
2650		{
2651			lock_block<mt_policy> lock(this);
2652			_connection6<desttype, arg1_type, arg2_type, arg3_type, arg4_type,
2653				arg5_type, arg6_type, mt_policy>* conn =
2654				new _connection6<desttype, arg1_type, arg2_type, arg3_type,
2655				arg4_type, arg5_type, arg6_type, mt_policy>(pclass, pmemfun);
2656			m_connected_slots.push_back(conn);
2657			pclass->signal_connect(this);
2658		}
2659
2660		void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
2661			arg5_type a5, arg6_type a6)
2662		{
2663			lock_block<mt_policy> lock(this);
2664			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2665			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2666
2667			while(it != itEnd)
2668			{
2669				itNext = it;
2670				++itNext;
2671
2672				(*it)->emit(a1, a2, a3, a4, a5, a6);
2673
2674				it = itNext;
2675			}
2676		}
2677
2678		void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
2679			arg5_type a5, arg6_type a6)
2680		{
2681			lock_block<mt_policy> lock(this);
2682			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2683			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2684
2685			while(it != itEnd)
2686			{
2687				itNext = it;
2688				++itNext;
2689
2690				(*it)->emit(a1, a2, a3, a4, a5, a6);
2691
2692				it = itNext;
2693			}
2694		}
2695	};
2696
2697	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
2698	class arg5_type, class arg6_type, class arg7_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
2699	class signal7 : public _signal_base7<arg1_type, arg2_type, arg3_type,
2700		arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>
2701	{
2702	public:
2703		typedef _signal_base7<arg1_type, arg2_type, arg3_type, arg4_type,
2704			arg5_type, arg6_type, arg7_type, mt_policy> base;
2705		typedef typename base::connections_list connections_list;
2706		using base::m_connected_slots;
2707
2708		signal7()
2709		{
2710			;
2711		}
2712
2713		signal7(const signal7<arg1_type, arg2_type, arg3_type, arg4_type,
2714			arg5_type, arg6_type, arg7_type, mt_policy>& s)
2715			: _signal_base7<arg1_type, arg2_type, arg3_type, arg4_type,
2716			arg5_type, arg6_type, arg7_type, mt_policy>(s)
2717		{
2718			;
2719		}
2720
2721		template<class desttype>
2722			void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
2723			arg2_type, arg3_type, arg4_type, arg5_type, arg6_type,
2724			arg7_type))
2725		{
2726			lock_block<mt_policy> lock(this);
2727			_connection7<desttype, arg1_type, arg2_type, arg3_type, arg4_type,
2728				arg5_type, arg6_type, arg7_type, mt_policy>* conn =
2729				new _connection7<desttype, arg1_type, arg2_type, arg3_type,
2730				arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>(pclass, pmemfun);
2731			m_connected_slots.push_back(conn);
2732			pclass->signal_connect(this);
2733		}
2734
2735		void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
2736			arg5_type a5, arg6_type a6, arg7_type a7)
2737		{
2738			lock_block<mt_policy> lock(this);
2739			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2740			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2741
2742			while(it != itEnd)
2743			{
2744				itNext = it;
2745				++itNext;
2746
2747				(*it)->emit(a1, a2, a3, a4, a5, a6, a7);
2748
2749				it = itNext;
2750			}
2751		}
2752
2753		void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
2754			arg5_type a5, arg6_type a6, arg7_type a7)
2755		{
2756			lock_block<mt_policy> lock(this);
2757			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2758			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2759
2760			while(it != itEnd)
2761			{
2762				itNext = it;
2763				++itNext;
2764
2765				(*it)->emit(a1, a2, a3, a4, a5, a6, a7);
2766
2767				it = itNext;
2768			}
2769		}
2770	};
2771
2772	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
2773	class arg5_type, class arg6_type, class arg7_type, class arg8_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
2774	class signal8 : public _signal_base8<arg1_type, arg2_type, arg3_type,
2775		arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>
2776	{
2777	public:
2778		typedef _signal_base8<arg1_type, arg2_type, arg3_type, arg4_type,
2779			arg5_type, arg6_type, arg7_type, arg8_type, mt_policy> base;
2780		typedef typename base::connections_list connections_list;
2781		using base::m_connected_slots;
2782
2783		signal8()
2784		{
2785			;
2786		}
2787
2788		signal8(const signal8<arg1_type, arg2_type, arg3_type, arg4_type,
2789			arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>& s)
2790			: _signal_base8<arg1_type, arg2_type, arg3_type, arg4_type,
2791			arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>(s)
2792		{
2793			;
2794		}
2795
2796		template<class desttype>
2797			void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
2798			arg2_type, arg3_type, arg4_type, arg5_type, arg6_type,
2799			arg7_type, arg8_type))
2800		{
2801			lock_block<mt_policy> lock(this);
2802			_connection8<desttype, arg1_type, arg2_type, arg3_type, arg4_type,
2803				arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* conn =
2804				new _connection8<desttype, arg1_type, arg2_type, arg3_type,
2805				arg4_type, arg5_type, arg6_type, arg7_type,
2806				arg8_type, mt_policy>(pclass, pmemfun);
2807			m_connected_slots.push_back(conn);
2808			pclass->signal_connect(this);
2809		}
2810
2811		void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
2812			arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8)
2813		{
2814			lock_block<mt_policy> lock(this);
2815			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2816			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2817
2818			while(it != itEnd)
2819			{
2820				itNext = it;
2821				++itNext;
2822
2823				(*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8);
2824
2825				it = itNext;
2826			}
2827		}
2828
2829		void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
2830			arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8)
2831		{
2832			lock_block<mt_policy> lock(this);
2833			typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
2834			typename connections_list::const_iterator itEnd = m_connected_slots.end();
2835
2836			while(it != itEnd)
2837			{
2838				itNext = it;
2839				++itNext;
2840
2841				(*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8);
2842
2843				it = itNext;
2844			}
2845		}
2846	};
2847
2848}; // namespace sigslot
2849
2850#endif // WEBRTC_BASE_SIGSLOT_H__
2851