1 // sigslot.h: Signal/Slot classes
2 //
3 // Written by Sarah Thompson (sarah@telergy.com) 2002.
4 // Additions by Barnaby Gray (barnaby@pickle.me.uk) 2002.
5 //
6 // License: Public domain. You are free to use this code however you like, with the proviso that
7 //          the author takes on no responsibility or liability for any use.
8 //
9 // This file is generated! DO NOT EDIT!
10 // Edit the original sigslot.pl script.
11 //
12 // QUICK DOCUMENTATION
13 //
14 //                              (see also the full documentation at http://sigslot.sourceforge.net/)
15 //
16 //              #define switches
17 //                      SIGSLOT_PURE_ISO                        - Define this to force ISO C++ compliance. This also disables
18 //                                                                                all of the thread safety support on platforms where it is
19 //                                                                                available.
20 //
21 //                      SIGSLOT_USE_POSIX_THREADS       - Force use of Posix threads when using a C++ compiler other than
22 //                                                                                gcc on a platform that supports Posix threads. (When using gcc,
23 //                                                                                this is the default - use SIGSLOT_PURE_ISO to disable this if
24 //                                                                                necessary)
25 //
26 //                      SIGSLOT_DEFAULT_MT_POLICY       - Where thread support is enabled, this defaults to multi_threaded_global.
27 //                                                                                Otherwise, the default is single_threaded. #define this yourself to
28 //                                                                                override the default. In pure ISO mode, anything other than
29 //                                                                                single_threaded will cause a compiler error.
30 //
31 //              PLATFORM NOTES
32 //
33 //                      Win32                                           - On Win32, the WIN32 symbol must be #defined. Most mainstream
34 //                                                                                compilers do this by default, but you may need to define it
35 //                                                                                yourself if your build environment is less standard. This causes
36 //                                                                                the Win32 thread support to be compiled in and used automatically.
37 //
38 //                      Unix/Linux/BSD, etc.            - If you're using gcc, it is assumed that you have Posix threads
39 //                                                                                available, so they are used automatically. You can override this
40 //                                                                                (as under Windows) with the SIGSLOT_PURE_ISO switch. If you're using
41 //                                                                                something other than gcc but still want to use Posix threads, you
42 //                                                                                need to #define SIGSLOT_USE_POSIX_THREADS.
43 //
44 //                      ISO C++                                         - If none of the supported platforms are detected, or if
45 //                                                                                SIGSLOT_PURE_ISO is defined, all multithreading support is turned off,
46 //                                                                                along with any code that might cause a pure ISO C++ environment to
47 //                                                                                complain. Before you ask, gcc -ansi -pedantic won't compile this
48 //                                                                                library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of
49 //                                                                                errors that aren't really there. If you feel like investigating this,
50 //                                                                                please contact the author.
51 //
52 //
53 //              THREADING MODES
54 //
55 //                      single_threaded                         - Your program is assumed to be single threaded from the point of view
56 //                                                                                of signal/slot usage (i.e. all objects using signals and slots are
57 //                                                                                created and destroyed from a single thread). Behaviour if objects are
58 //                                                                                destroyed concurrently is undefined (i.e. you'll get the occasional
59 //                                                                                segmentation fault/memory exception).
60 //
61 //                      multi_threaded_global           - Your program is assumed to be multi threaded. Objects using signals and
62 //                                                                                slots can be safely created and destroyed from any thread, even when
63 //                                                                                connections exist. In multi_threaded_global mode, this is achieved by a
64 //                                                                                single global mutex (actually a critical section on Windows because they
65 //                                                                                are faster). This option uses less OS resources, but results in more
66 //                                                                                opportunities for contention, possibly resulting in more context switches
67 //                                                                                than are strictly necessary.
68 //
69 //                      multi_threaded_local            - Behaviour in this mode is essentially the same as multi_threaded_global,
70 //                                                                                except that each signal, and each object that inherits has_slots, all
71 //                                                                                have their own mutex/critical section. In practice, this means that
72 //                                                                                mutex collisions (and hence context switches) only happen if they are
73 //                                                                                absolutely essential. However, on some platforms, creating a lot of
74 //                                                                                mutexes can slow down the whole OS, so use this option with care.
75 //
76 //              USING THE LIBRARY
77 //
78 //                      See the full documentation at http://sigslot.sourceforge.net/
79 //
80 //
81 
82 #ifndef SIGSLOT_H__
83 #define SIGSLOT_H__
84 
85 #include <set>
86 #include <list>
87 #include <cstddef>
88 
89 #if defined(SIGSLOT_PURE_ISO) || (!defined(WIN32) && !defined(SIGSLOT_USE_POSIX_THREADS))
90 #       define _SIGSLOT_SINGLE_THREADED
91 #elif defined(WIN32)
92 #       define _SIGSLOT_HAS_WIN32_THREADS
93 #       include <windows.h>
94 #elif defined(SIGSLOT_USE_POSIX_THREADS)
95 #       define _SIGSLOT_HAS_POSIX_THREADS
96 #       include <pthread.h>
97 #else
98 #       define _SIGSLOT_SINGLE_THREADED
99 #endif
100 
101 #ifndef SIGSLOT_DEFAULT_MT_POLICY
102 #       ifdef _SIGSLOT_SINGLE_THREADED
103 #               define SIGSLOT_DEFAULT_MT_POLICY single_threaded
104 #       else
105 #               define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local
106 #       endif
107 #endif
108 
109 
110 namespace sigslot {
111 
112 	class single_threaded
113 	{
114 	public:
single_threaded()115 		single_threaded()
116 		{
117 			;
118 		}
119 
~single_threaded()120 		virtual ~single_threaded()
121 		{
122 			;
123 		}
124 
lock()125 		virtual void lock()
126 		{
127 			;
128 		}
129 
unlock()130 		virtual void unlock()
131 		{
132 			;
133 		}
134 	};
135 
136 #ifdef _SIGSLOT_HAS_WIN32_THREADS
137 	// The multi threading policies only get compiled in if they are enabled.
138 	class multi_threaded_global
139 	{
140 	public:
multi_threaded_global()141 		multi_threaded_global()
142 		{
143 			static bool isinitialised = false;
144 
145 			if(!isinitialised)
146 			{
147 				InitializeCriticalSection(get_critsec());
148 				isinitialised = true;
149 			}
150 		}
151 
multi_threaded_global(const multi_threaded_global &)152 		multi_threaded_global(const multi_threaded_global&)
153 		{
154 			;
155 		}
156 
~multi_threaded_global()157 		virtual ~multi_threaded_global()
158 		{
159 			;
160 		}
161 
lock()162 		virtual void lock()
163 		{
164 			EnterCriticalSection(get_critsec());
165 		}
166 
unlock()167 		virtual void unlock()
168 		{
169 			LeaveCriticalSection(get_critsec());
170 		}
171 
172 	private:
get_critsec()173 		CRITICAL_SECTION* get_critsec()
174 		{
175 			static CRITICAL_SECTION g_critsec;
176 			return &g_critsec;
177 		}
178 	};
179 
180 	class multi_threaded_local
181 	{
182 	public:
multi_threaded_local()183 		multi_threaded_local()
184 		{
185 			InitializeCriticalSection(&m_critsec);
186 		}
187 
multi_threaded_local(const multi_threaded_local &)188 		multi_threaded_local(const multi_threaded_local&)
189 		{
190 			InitializeCriticalSection(&m_critsec);
191 		}
192 
~multi_threaded_local()193 		virtual ~multi_threaded_local()
194 		{
195 			DeleteCriticalSection(&m_critsec);
196 		}
197 
lock()198 		virtual void lock()
199 		{
200 			EnterCriticalSection(&m_critsec);
201 		}
202 
unlock()203 		virtual void unlock()
204 		{
205 			LeaveCriticalSection(&m_critsec);
206 		}
207 
208 	private:
209 		CRITICAL_SECTION m_critsec;
210 	};
211 #endif // _SIGSLOT_HAS_WIN32_THREADS
212 
213 #ifdef _SIGSLOT_HAS_POSIX_THREADS
214 	// The multi threading policies only get compiled in if they are enabled.
215 	class multi_threaded_global
216 	{
217 	public:
multi_threaded_global()218 		multi_threaded_global()
219 		{
220 			pthread_mutex_init(get_mutex(), NULL);
221 		}
222 
multi_threaded_global(const multi_threaded_global &)223 		multi_threaded_global(const multi_threaded_global&)
224 		{
225 			;
226 		}
227 
~multi_threaded_global()228 		virtual ~multi_threaded_global()
229 		{
230 			;
231 		}
232 
lock()233 		virtual void lock()
234 		{
235 			pthread_mutex_lock(get_mutex());
236 		}
237 
unlock()238 		virtual void unlock()
239 		{
240 			pthread_mutex_unlock(get_mutex());
241 		}
242 
243 	private:
get_mutex()244 		pthread_mutex_t* get_mutex()
245 		{
246 			static pthread_mutex_t g_mutex;
247 			return &g_mutex;
248 		}
249 	};
250 
251 	class multi_threaded_local
252 	{
253 	public:
multi_threaded_local()254 		multi_threaded_local()
255 		{
256 			pthread_mutex_init(&m_mutex, NULL);
257 		}
258 
multi_threaded_local(const multi_threaded_local &)259 		multi_threaded_local(const multi_threaded_local&)
260 		{
261 			pthread_mutex_init(&m_mutex, NULL);
262 		}
263 
~multi_threaded_local()264 		virtual ~multi_threaded_local()
265 		{
266 			pthread_mutex_destroy(&m_mutex);
267 		}
268 
lock()269 		virtual void lock()
270 		{
271 			pthread_mutex_lock(&m_mutex);
272 		}
273 
unlock()274 		virtual void unlock()
275 		{
276 			pthread_mutex_unlock(&m_mutex);
277 		}
278 
279 	private:
280 		pthread_mutex_t m_mutex;
281 	};
282 #endif // _SIGSLOT_HAS_POSIX_THREADS
283 
284 	template<class mt_policy>
285 	class lock_block
286 	{
287 	public:
288 		mt_policy *m_mutex;
289 
lock_block(mt_policy * mtx)290 		lock_block(mt_policy *mtx)
291 			: m_mutex(mtx)
292 		{
293 			m_mutex->lock();
294 		}
295 
~lock_block()296 		~lock_block()
297 		{
298 			m_mutex->unlock();
299 		}
300 	};
301 
302 	template<class mt_policy>
303 	class has_slots;
304 
305 	template<class mt_policy>
306 	class _connection_base0
307 	{
308 	public:
309 		virtual has_slots<mt_policy>* getdest() const = 0;
310 		virtual void emit() = 0;
311 		virtual _connection_base0<mt_policy>* clone() = 0;
312 		virtual _connection_base0<mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
313 	};
314 
315 	template<class arg1_type, class mt_policy>
316 	class _connection_base1
317 	{
318 	public:
319 		virtual has_slots<mt_policy>* getdest() const = 0;
320 		virtual void emit(arg1_type) = 0;
321 		virtual _connection_base1<arg1_type, mt_policy>* clone() = 0;
322 		virtual _connection_base1<arg1_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
323 	};
324 
325 	template<class arg1_type, class arg2_type, class mt_policy>
326 	class _connection_base2
327 	{
328 	public:
329 		virtual has_slots<mt_policy>* getdest() const = 0;
330 		virtual void emit(arg1_type, arg2_type) = 0;
331 		virtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone() = 0;
332 		virtual _connection_base2<arg1_type, arg2_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
333 	};
334 
335 	template<class mt_policy>
336 	class _signal_base : public has_slots<mt_policy>
337 	{
338 	public:
339 		virtual void slot_disconnect(has_slots<mt_policy>* pslot) = 0;
340 		virtual void slot_duplicate(const has_slots<mt_policy>* poldslot, has_slots<mt_policy>* pnewslot) = 0;
341 	};
342 
343 	template<class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
344 	class has_slots : public mt_policy
345 	{
346 	private:
347 		typedef std::set<_signal_base<mt_policy> *> sender_set;
348 		typedef typename sender_set::const_iterator const_iterator;
349 
350 	public:
has_slots()351 		has_slots()
352 		{
353 			;
354 		}
355 
has_slots(const has_slots & hs)356 		has_slots(const has_slots& hs)
357 			: mt_policy(hs)
358 		{
359 			lock_block<mt_policy> lock(this);
360 			const_iterator it = hs.m_senders.begin();
361 			const_iterator itEnd = hs.m_senders.end();
362 
363 			while(it != itEnd)
364 			{
365 				(*it)->slot_duplicate(&hs, this);
366 				m_senders.insert(*it);
367 				++it;
368 			}
369 		}
370 
signal_connect(_signal_base<mt_policy> * sender)371 		void signal_connect(_signal_base<mt_policy>* sender)
372 		{
373 			lock_block<mt_policy> lock(this);
374 			m_senders.insert(sender);
375 		}
376 
signal_disconnect(_signal_base<mt_policy> * sender)377 		void signal_disconnect(_signal_base<mt_policy>* sender)
378 		{
379 			lock_block<mt_policy> lock(this);
380 			m_senders.erase(sender);
381 		}
382 
~has_slots()383 		virtual ~has_slots()
384 		{
385 			disconnect_all();
386 		}
387 
disconnect_all()388 		void disconnect_all()
389 		{
390 			lock_block<mt_policy> lock(this);
391 			const_iterator it = m_senders.begin();
392 			const_iterator itEnd = m_senders.end();
393 
394 			while(it != itEnd)
395 			{
396 				(*it)->slot_disconnect(this);
397 				++it;
398 			}
399 
400 			m_senders.erase(m_senders.begin(), m_senders.end());
401 		}
402 
403 	private:
404 		sender_set m_senders;
405 	};
406 
407 	template<class mt_policy>
408 	class _signal_base0 : public _signal_base<mt_policy>
409 	{
410 	public:
411 		typedef typename std::list<_connection_base0<mt_policy> *>
412 			connections_list;
413 
_signal_base0()414 		_signal_base0()
415 		{
416 			;
417 		}
418 
_signal_base0(const _signal_base0<mt_policy> & s)419 		_signal_base0(const _signal_base0<mt_policy>& s)
420 			: _signal_base<mt_policy>(s)
421 		{
422 			lock_block<mt_policy> lock(this);
423 			typename connections_list::const_iterator it = s.m_connected_slots.begin();
424 			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
425 
426 			while(it != itEnd)
427 			{
428 				(*it)->getdest()->signal_connect(this);
429 				m_connected_slots.push_back((*it)->clone());
430 
431 				++it;
432 			}
433 		}
434 
slot_duplicate(const has_slots<mt_policy> * oldtarget,has_slots<mt_policy> * newtarget)435 		void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
436 		{
437 			lock_block<mt_policy> lock(this);
438 			typename connections_list::iterator it = m_connected_slots.begin();
439 			typename connections_list::iterator itEnd = m_connected_slots.end();
440 
441 			while(it != itEnd)
442 			{
443 				if((*it)->getdest() == oldtarget)
444 				{
445 					m_connected_slots.push_back((*it)->duplicate(newtarget));
446 				}
447 
448 				++it;
449 			}
450 		}
451 
~_signal_base0()452 		~_signal_base0()
453 		{
454 			disconnect_all();
455 		}
456 
disconnect_all()457 		void disconnect_all()
458 		{
459 			lock_block<mt_policy> lock(this);
460 			typename connections_list::const_iterator it = m_connected_slots.begin();
461 			typename connections_list::const_iterator itEnd = m_connected_slots.end();
462 
463 			while(it != itEnd)
464 			{
465 				(*it)->getdest()->signal_disconnect(this);
466 				delete *it;
467 
468 				++it;
469 			}
470 
471 			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
472 		}
473 
disconnect(has_slots<mt_policy> * pclass)474 		void disconnect(has_slots<mt_policy>* pclass)
475 		{
476 			lock_block<mt_policy> lock(this);
477 			typename connections_list::iterator it = m_connected_slots.begin();
478 			typename connections_list::iterator itEnd = m_connected_slots.end();
479 
480 			while(it != itEnd)
481 			{
482 				typename connections_list::iterator itNext = it;
483 				++itNext;
484 
485 				if((*it)->getdest() == pclass)
486 				{
487 					delete *it;
488 					m_connected_slots.erase(it);
489 					pclass->signal_disconnect(this);
490 					return;
491 				}
492 
493 				it = itNext;
494 			}
495 		}
496 
slot_disconnect(has_slots<mt_policy> * pslot)497 		void slot_disconnect(has_slots<mt_policy>* pslot)
498 		{
499 			lock_block<mt_policy> lock(this);
500 			typename connections_list::iterator it = m_connected_slots.begin();
501 			typename connections_list::iterator itEnd = m_connected_slots.end();
502 
503 			while(it != itEnd)
504 			{
505 				typename connections_list::iterator itNext = it;
506 				++itNext;
507 
508 				if((*it)->getdest() == pslot)
509 				{
510 					delete *it;
511 					m_connected_slots.erase(it);
512 				}
513 
514 				it = itNext;
515 			}
516 		}
517 
518 	protected:
519 		connections_list m_connected_slots;
520 	};
521 
522 	template<class arg1_type, class mt_policy>
523 	class _signal_base1 : public _signal_base<mt_policy>
524 	{
525 	public:
526 		typedef typename std::list<_connection_base1<arg1_type, mt_policy> *>
527 			connections_list;
528 
_signal_base1()529 		_signal_base1()
530 		{
531 			;
532 		}
533 
_signal_base1(const _signal_base1<arg1_type,mt_policy> & s)534 		_signal_base1(const _signal_base1<arg1_type, mt_policy>& s)
535 			: _signal_base<mt_policy>(s)
536 		{
537 			lock_block<mt_policy> lock(this);
538 			typename connections_list::const_iterator it = s.m_connected_slots.begin();
539 			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
540 
541 			while(it != itEnd)
542 			{
543 				(*it)->getdest()->signal_connect(this);
544 				m_connected_slots.push_back((*it)->clone());
545 
546 				++it;
547 			}
548 		}
549 
slot_duplicate(const has_slots<mt_policy> * oldtarget,has_slots<mt_policy> * newtarget)550 		void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
551 		{
552 			lock_block<mt_policy> lock(this);
553 			typename connections_list::iterator it = m_connected_slots.begin();
554 			typename connections_list::iterator itEnd = m_connected_slots.end();
555 
556 			while(it != itEnd)
557 			{
558 				if((*it)->getdest() == oldtarget)
559 				{
560 					m_connected_slots.push_back((*it)->duplicate(newtarget));
561 				}
562 
563 				++it;
564 			}
565 		}
566 
~_signal_base1()567 		~_signal_base1()
568 		{
569 			disconnect_all();
570 		}
571 
disconnect_all()572 		void disconnect_all()
573 		{
574 			lock_block<mt_policy> lock(this);
575 			typename connections_list::const_iterator it = m_connected_slots.begin();
576 			typename connections_list::const_iterator itEnd = m_connected_slots.end();
577 
578 			while(it != itEnd)
579 			{
580 				(*it)->getdest()->signal_disconnect(this);
581 				delete *it;
582 
583 				++it;
584 			}
585 
586 			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
587 		}
588 
disconnect(has_slots<mt_policy> * pclass)589 		void disconnect(has_slots<mt_policy>* pclass)
590 		{
591 			lock_block<mt_policy> lock(this);
592 			typename connections_list::iterator it = m_connected_slots.begin();
593 			typename connections_list::iterator itEnd = m_connected_slots.end();
594 
595 			while(it != itEnd)
596 			{
597 				typename connections_list::iterator itNext = it;
598 				++itNext;
599 
600 				if((*it)->getdest() == pclass)
601 				{
602 					delete *it;
603 					m_connected_slots.erase(it);
604 					pclass->signal_disconnect(this);
605 					return;
606 				}
607 
608 				it = itNext;
609 			}
610 		}
611 
slot_disconnect(has_slots<mt_policy> * pslot)612 		void slot_disconnect(has_slots<mt_policy>* pslot)
613 		{
614 			lock_block<mt_policy> lock(this);
615 			typename connections_list::iterator it = m_connected_slots.begin();
616 			typename connections_list::iterator itEnd = m_connected_slots.end();
617 
618 			while(it != itEnd)
619 			{
620 				typename connections_list::iterator itNext = it;
621 				++itNext;
622 
623 				if((*it)->getdest() == pslot)
624 				{
625 					delete *it;
626 					m_connected_slots.erase(it);
627 				}
628 
629 				it = itNext;
630 			}
631 		}
632 
633 	protected:
634 		connections_list m_connected_slots;
635 	};
636 
637 	template<class arg1_type, class arg2_type, class mt_policy>
638 	class _signal_base2 : public _signal_base<mt_policy>
639 	{
640 	public:
641 		typedef typename std::list<_connection_base2<arg1_type, arg2_type, mt_policy> *>
642 			connections_list;
643 
_signal_base2()644 		_signal_base2()
645 		{
646 			;
647 		}
648 
_signal_base2(const _signal_base2<arg1_type,arg2_type,mt_policy> & s)649 		_signal_base2(const _signal_base2<arg1_type, arg2_type, mt_policy>& s)
650 			: _signal_base<mt_policy>(s)
651 		{
652 			lock_block<mt_policy> lock(this);
653 			typename connections_list::const_iterator it = s.m_connected_slots.begin();
654 			typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
655 
656 			while(it != itEnd)
657 			{
658 				(*it)->getdest()->signal_connect(this);
659 				m_connected_slots.push_back((*it)->clone());
660 
661 				++it;
662 			}
663 		}
664 
slot_duplicate(const has_slots<mt_policy> * oldtarget,has_slots<mt_policy> * newtarget)665 		void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
666 		{
667 			lock_block<mt_policy> lock(this);
668 			typename connections_list::iterator it = m_connected_slots.begin();
669 			typename connections_list::iterator itEnd = m_connected_slots.end();
670 
671 			while(it != itEnd)
672 			{
673 				if((*it)->getdest() == oldtarget)
674 				{
675 					m_connected_slots.push_back((*it)->duplicate(newtarget));
676 				}
677 
678 				++it;
679 			}
680 		}
681 
~_signal_base2()682 		~_signal_base2()
683 		{
684 			disconnect_all();
685 		}
686 
disconnect_all()687 		void disconnect_all()
688 		{
689 			lock_block<mt_policy> lock(this);
690 			typename connections_list::const_iterator it = m_connected_slots.begin();
691 			typename connections_list::const_iterator itEnd = m_connected_slots.end();
692 
693 			while(it != itEnd)
694 			{
695 				(*it)->getdest()->signal_disconnect(this);
696 				delete *it;
697 
698 				++it;
699 			}
700 
701 			m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
702 		}
703 
disconnect(has_slots<mt_policy> * pclass)704 		void disconnect(has_slots<mt_policy>* pclass)
705 		{
706 			lock_block<mt_policy> lock(this);
707 			typename connections_list::iterator it = m_connected_slots.begin();
708 			typename connections_list::iterator itEnd = m_connected_slots.end();
709 
710 			while(it != itEnd)
711 			{
712 				typename connections_list::iterator itNext = it;
713 				++itNext;
714 				if((*it)->getdest() == pclass)
715 				{
716 					delete *it;
717 					m_connected_slots.erase(it);
718 					pclass->signal_disconnect(this);
719 					return;
720 				}
721 
722 				it = itNext;
723 			}
724 		}
725 
slot_disconnect(has_slots<mt_policy> * pslot)726 		void slot_disconnect(has_slots<mt_policy>* pslot)
727 		{
728 			lock_block<mt_policy> lock(this);
729 			typename connections_list::iterator it = m_connected_slots.begin();
730 			typename connections_list::iterator itEnd = m_connected_slots.end();
731 
732 			while(it != itEnd)
733 			{
734 				typename connections_list::iterator itNext = it;
735 				++itNext;
736 
737 				if((*it)->getdest() == pslot)
738 				{
739 					delete *it;
740 					m_connected_slots.erase(it);
741 				}
742 
743 				it = itNext;
744 			}
745 		}
746 
747 	protected:
748 		connections_list m_connected_slots;
749 	};
750 
751 	template<class dest_type, class mt_policy>
752 	class _connection0 : public _connection_base0<mt_policy>
753 	{
754 	public:
_connection0()755 		_connection0()
756 		{
757 			this->pobject = NULL;
758 			this->pmemfun = NULL;
759 		}
760 
_connection0(dest_type * pobject,void (dest_type::* pmemfun)())761 		_connection0(dest_type* pobject, void (dest_type::*pmemfun)())
762 		{
763 			m_pobject = pobject;
764 			m_pmemfun = pmemfun;
765 		}
766 
clone()767 		virtual _connection_base0<mt_policy>* clone()
768 		{
769 			return new _connection0<dest_type, mt_policy>(*this);
770 		}
771 
duplicate(has_slots<mt_policy> * pnewdest)772 		virtual _connection_base0<mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
773 		{
774 			return new _connection0<dest_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
775 		}
776 
emit()777 		virtual void emit()
778 		{
779 			(m_pobject->*m_pmemfun)();
780 		}
781 
getdest()782 		virtual has_slots<mt_policy>* getdest() const
783 		{
784 			return m_pobject;
785 		}
786 
787 	private:
788 		dest_type* m_pobject;
789 		void (dest_type::* m_pmemfun)();
790 	};
791 
792 	template<class dest_type, class arg1_type, class mt_policy>
793 	class _connection1 : public _connection_base1<arg1_type, mt_policy>
794 	{
795 	public:
_connection1()796 		_connection1()
797 		{
798 			this->pobject = NULL;
799 			this->pmemfun = NULL;
800 		}
801 
_connection1(dest_type * pobject,void (dest_type::* pmemfun)(arg1_type))802 		_connection1(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type))
803 		{
804 			m_pobject = pobject;
805 			m_pmemfun = pmemfun;
806 		}
807 
clone()808 		virtual _connection_base1<arg1_type, mt_policy>* clone()
809 		{
810 			return new _connection1<dest_type, arg1_type, mt_policy>(*this);
811 		}
812 
duplicate(has_slots<mt_policy> * pnewdest)813 		virtual _connection_base1<arg1_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
814 		{
815 			return new _connection1<dest_type, arg1_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
816 		}
817 
emit(arg1_type a1)818 		virtual void emit(arg1_type a1)
819 		{
820 			(m_pobject->*m_pmemfun)(a1);
821 		}
822 
getdest()823 		virtual has_slots<mt_policy>* getdest() const
824 		{
825 			return m_pobject;
826 		}
827 
828 	private:
829 		dest_type* m_pobject;
830 		void (dest_type::* m_pmemfun)(arg1_type);
831 	};
832 
833 	template<class dest_type, class arg1_type, class arg2_type, class mt_policy>
834 	class _connection2 : public _connection_base2<arg1_type, arg2_type, mt_policy>
835 	{
836 	public:
_connection2()837 		_connection2()
838 		{
839 			this->pobject = NULL;
840 			this->pmemfun = NULL;
841 		}
842 
_connection2(dest_type * pobject,void (dest_type::* pmemfun)(arg1_type,arg2_type))843 		_connection2(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, arg2_type))
844 		{
845 			m_pobject = pobject;
846 			m_pmemfun = pmemfun;
847 		}
848 
clone()849 		virtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone()
850 		{
851 			return new _connection2<dest_type, arg1_type, arg2_type, mt_policy>(*this);
852 		}
853 
duplicate(has_slots<mt_policy> * pnewdest)854 		virtual _connection_base2<arg1_type, arg2_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
855 		{
856 			return new _connection2<dest_type, arg1_type, arg2_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
857 		}
858 
emit(arg1_type a1,arg2_type a2)859 		virtual void emit(arg1_type a1, arg2_type a2)
860 		{
861 			(m_pobject->*m_pmemfun)(a1, a2);
862 		}
863 
getdest()864 		virtual has_slots<mt_policy>* getdest() const
865 		{
866 			return m_pobject;
867 		}
868 
869 	private:
870 		dest_type* m_pobject;
871 		void (dest_type::* m_pmemfun)(arg1_type, arg2_type);
872 	};
873 
874 	template<class mt_policy>
875 	class _sig_connection0;
876 	template<class arg1_type, class mt_policy>
877 	class _sig_connection1;
878 	template<class arg1_type, class arg2_type, class mt_policy>
879 	class _sig_connection2;
880 	template<class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
881 	class signal0 : public _signal_base0<mt_policy>
882 	{
883 	public:
signal0()884 		signal0()
885 		{
886 			;
887 		}
888 
signal0(const signal0<mt_policy> & s)889 		signal0(const signal0<mt_policy>& s)
890 			: _signal_base0<mt_policy>(s)
891 		{
892 			;
893 		}
894 
895 		template<class dest_type>
connect(dest_type * pclass,void (dest_type::* pmemfun)())896 			void connect(dest_type* pclass, void (dest_type::*pmemfun)())
897 		{
898 			lock_block<mt_policy> lock(this);
899 			_connection0<dest_type, mt_policy>* conn
900 			    = new _connection0<dest_type, mt_policy>(pclass, pmemfun);
901 			this->m_connected_slots.push_back(conn);
902 			pclass->signal_connect(this);
903 		}
904 
connect(signal0<mt_policy> & chainsig)905 		void connect(signal0<mt_policy>& chainsig)
906 		{
907 			lock_block<mt_policy> lock(this);
908 			_sig_connection0<mt_policy>* conn = new _sig_connection0<mt_policy>(chainsig);
909 			this->m_connected_slots.push_back(conn);
910 			chainsig.signal_connect(this);
911 		}
912 
emit()913 		void emit()
914 		{
915 			lock_block<mt_policy> lock(this);
916 			typename _signal_base0< mt_policy >::connections_list::const_iterator itNext, it = this->m_connected_slots.begin();
917 			typename _signal_base0< mt_policy >::connections_list::const_iterator itEnd = this->m_connected_slots.end();
918 
919 			while(it != itEnd)
920 			{
921 				itNext = it;
922 				++itNext;
923 
924 				(*it)->emit();
925 
926 				it = itNext;
927 			}
928 		}
929 
operator()930 		void operator()()
931 		{
932 			lock_block<mt_policy> lock(this);
933 			typename _signal_base0< mt_policy >::connections_list::connections_list::const_iterator itNext, it = this->m_connected_slots.begin();
934 			typename _signal_base0< mt_policy >::connections_list::connections_list::const_iterator itEnd = this->m_connected_slots.end();
935 
936 			while(it != itEnd)
937 			{
938 				itNext = it;
939 				++itNext;
940 
941 				(*it)->emit();
942 
943 				it = itNext;
944 			}
945 		}
946 	};
947 
948 	template<class arg1_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
949 	class signal1 : public _signal_base1<arg1_type, mt_policy>
950 	{
951 	public:
signal1()952 		signal1()
953 		{
954 			;
955 		}
956 
signal1(const signal1<arg1_type,mt_policy> & s)957 		signal1(const signal1<arg1_type, mt_policy>& s)
958 			: _signal_base1<arg1_type, mt_policy>(s)
959 		{
960 			;
961 		}
962 
963 		template<class dest_type>
connect(dest_type * pclass,void (dest_type::* pmemfun)(arg1_type))964 			void connect(dest_type* pclass, void (dest_type::*pmemfun)(arg1_type))
965 		{
966 			lock_block<mt_policy> lock(this);
967 			_connection1<dest_type, arg1_type, mt_policy>* conn
968 			    = new _connection1<dest_type, arg1_type, mt_policy>(pclass, pmemfun);
969 			this->m_connected_slots.push_back(conn);
970 			pclass->signal_connect(this);
971 		}
972 
connect(signal1<arg1_type,mt_policy> & chainsig)973 		void connect(signal1<arg1_type, mt_policy>& chainsig)
974 		{
975 			lock_block<mt_policy> lock(this);
976 			_sig_connection1<arg1_type, mt_policy>* conn = new _sig_connection1<arg1_type, mt_policy>(chainsig);
977 			this->m_connected_slots.push_back(conn);
978 			chainsig.signal_connect(this);
979 		}
980 
emit(arg1_type a1)981 		void emit(arg1_type a1)
982 		{
983 			lock_block<mt_policy> lock(this);
984 			typename _signal_base1<arg1_type, mt_policy >::connections_list::const_iterator itNext, it = this->m_connected_slots.begin();
985 			typename _signal_base1<arg1_type, mt_policy >::connections_list::const_iterator itEnd = this->m_connected_slots.end();
986 
987 			while(it != itEnd)
988 			{
989 				itNext = it;
990 				++itNext;
991 
992 				(*it)->emit(a1);
993 
994 				it = itNext;
995 			}
996 		}
997 
operator()998 		void operator()(arg1_type a1)
999 		{
1000 			lock_block<mt_policy> lock(this);
1001 			typename _signal_base1<arg1_type, mt_policy >::connections_list::const_iterator itNext, it = this->m_connected_slots.begin();
1002 			typename _signal_base1<arg1_type, mt_policy >::connections_list::const_iterator itEnd = this->m_connected_slots.end();
1003 
1004 			while(it != itEnd)
1005 			{
1006 				itNext = it;
1007 				++itNext;
1008 
1009 				(*it)->emit(a1);
1010 
1011 				it = itNext;
1012 			}
1013 		}
1014 	};
1015 
1016 	template<class arg1_type, class arg2_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
1017 	class signal2 : public _signal_base2<arg1_type, arg2_type, mt_policy>
1018 	{
1019 	public:
signal2()1020 		signal2()
1021 		{
1022 			;
1023 		}
1024 
signal2(const signal2<arg1_type,arg2_type,mt_policy> & s)1025 		signal2(const signal2<arg1_type, arg2_type, mt_policy>& s)
1026 			: _signal_base2<arg1_type, arg2_type, mt_policy>(s)
1027 		{
1028 			;
1029 		}
1030 
1031 		template<class dest_type>
connect(dest_type * pclass,void (dest_type::* pmemfun)(arg1_type,arg2_type))1032 			void connect(dest_type* pclass, void (dest_type::*pmemfun)(arg1_type, arg2_type))
1033 		{
1034 			lock_block<mt_policy> lock(this);
1035 			_connection2<dest_type, arg1_type, arg2_type, mt_policy>* conn
1036 			    = new _connection2<dest_type, arg1_type, arg2_type, mt_policy>(pclass, pmemfun);
1037 			this->m_connected_slots.push_back(conn);
1038 			pclass->signal_connect(this);
1039 		}
1040 
connect(signal2<arg1_type,arg2_type,mt_policy> & chainsig)1041 		void connect(signal2<arg1_type, arg2_type, mt_policy>& chainsig)
1042 		{
1043 			lock_block<mt_policy> lock(this);
1044 			_sig_connection2<arg1_type, arg2_type, mt_policy>* conn = new _sig_connection2<arg1_type, arg2_type, mt_policy>(chainsig);
1045 			this->m_connected_slots.push_back(conn);
1046 			chainsig.signal_connect(this);
1047 		}
1048 
emit(arg1_type a1,arg2_type a2)1049 		void emit(arg1_type a1, arg2_type a2)
1050 		{
1051 			lock_block<mt_policy> lock(this);
1052 			typename _signal_base2<arg1_type, arg2_type, mt_policy>::connections_list::const_iterator itNext, it = this->m_connected_slots.begin();
1053 			typename _signal_base2<arg1_type, arg2_type, mt_policy>::connections_list::const_iterator itEnd = this->m_connected_slots.end();
1054 
1055 			while(it != itEnd)
1056 			{
1057 				itNext = it;
1058 				++itNext;
1059 
1060 				(*it)->emit(a1, a2);
1061 
1062 				it = itNext;
1063 			}
1064 		}
1065 
operator()1066 		void operator()(arg1_type a1, arg2_type a2)
1067 		{
1068 			lock_block<mt_policy> lock(this);
1069 			typename _signal_base2<arg1_type, arg2_type, mt_policy>::connections_list::const_iterator itNext, it = this->m_connected_slots.begin();
1070 			typename _signal_base2<arg1_type, arg2_type, mt_policy>::connections_list::const_iterator itEnd = this->m_connected_slots.end();
1071 
1072 			while(it != itEnd)
1073 			{
1074 				itNext = it;
1075 				++itNext;
1076 
1077 				(*it)->emit(a1, a2);
1078 
1079 				it = itNext;
1080 			}
1081 		}
1082 	};
1083 
1084 // signal chaining connection types added by Barnaby Gray 24/11/2002
1085 
1086 	template<class mt_policy>
1087 	class _sig_connection0 : public _connection_base0<mt_policy>
1088 	{
1089 	public:
_sig_connection0(signal0<mt_policy> & sig)1090 		_sig_connection0(signal0<mt_policy>& sig)
1091 		: m_signal(sig)
1092 		{
1093 		}
1094 
_sig_connection0(const _sig_connection0<mt_policy> & conn)1095 		_sig_connection0(const _sig_connection0<mt_policy>& conn)
1096 		: m_signal( conn.m_signal )
1097 		{
1098 		}
1099 
clone()1100 		virtual _connection_base0<mt_policy>* clone()
1101 		{
1102 			return new _sig_connection0<mt_policy>(*this);
1103 		}
1104 
duplicate(has_slots<mt_policy> * pnewdest)1105 		virtual _connection_base0<mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
1106 		{
1107 			return new _sig_connection0<mt_policy>(m_signal);
1108 		}
1109 
emit()1110 		virtual void emit()
1111 		{
1112 			m_signal.emit();
1113 		}
1114 
getdest()1115 		virtual has_slots<mt_policy>* getdest() const
1116 		{
1117 			return &m_signal;
1118 		}
1119 
1120 	private:
1121 		signal0<mt_policy>& m_signal;
1122 	};
1123 
1124 	template<class arg1_type, class mt_policy>
1125 	class _sig_connection1 : public _connection_base1<arg1_type, mt_policy>
1126 	{
1127 	public:
_sig_connection1(signal1<arg1_type,mt_policy> & sig)1128 		_sig_connection1(signal1<arg1_type, mt_policy>& sig)
1129 		: m_signal(sig)
1130 		{
1131 		}
1132 
_sig_connection1(const _sig_connection1<arg1_type,mt_policy> & conn)1133 		_sig_connection1(const _sig_connection1<arg1_type, mt_policy>& conn)
1134 		: m_signal( conn.m_signal )
1135 		{
1136 		}
1137 
clone()1138 		virtual _connection_base1<arg1_type, mt_policy>* clone()
1139 		{
1140 			return new _sig_connection1<arg1_type, mt_policy>(*this);
1141 		}
1142 
duplicate(has_slots<mt_policy> * pnewdest)1143 		virtual _connection_base1<arg1_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
1144 		{
1145 			return new _sig_connection1<arg1_type, mt_policy>(m_signal);
1146 		}
1147 
emit(arg1_type a1)1148 		virtual void emit(arg1_type a1)
1149 		{
1150 			m_signal.emit(a1);
1151 		}
1152 
getdest()1153 		virtual has_slots<mt_policy>* getdest() const
1154 		{
1155 			return &m_signal;
1156 		}
1157 
1158 	private:
1159 		signal1<arg1_type, mt_policy>& m_signal;
1160 	};
1161 
1162 	template<class arg1_type, class arg2_type, class mt_policy>
1163 	class _sig_connection2 : public _connection_base2<arg1_type, arg2_type, mt_policy>
1164 	{
1165 	public:
_sig_connection2(signal2<arg1_type,arg2_type,mt_policy> & sig)1166 		_sig_connection2(signal2<arg1_type, arg2_type, mt_policy>& sig)
1167 		: m_signal(sig)
1168 		{
1169 		}
1170 
_sig_connection2(const _sig_connection2<arg1_type,arg2_type,mt_policy> & conn)1171 		_sig_connection2(const _sig_connection2<arg1_type, arg2_type, mt_policy>& conn)
1172 		: m_signal( conn.m_signal )
1173 		{
1174 		}
1175 
clone()1176 		virtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone()
1177 		{
1178 			return new _sig_connection2<arg1_type, arg2_type, mt_policy>(*this);
1179 		}
1180 
duplicate(has_slots<mt_policy> * pnewdest)1181 		virtual _connection_base2<arg1_type, arg2_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
1182 		{
1183 			return new _sig_connection2<arg1_type, arg2_type, mt_policy>(m_signal);
1184 		}
1185 
emit(arg1_type a1,arg2_type a2)1186 		virtual void emit(arg1_type a1, arg2_type a2)
1187 		{
1188 			m_signal.emit(a1, a2);
1189 		}
1190 
getdest()1191 		virtual has_slots<mt_policy>* getdest() const
1192 		{
1193 			return &m_signal;
1194 		}
1195 
1196 	private:
1197 		signal2<arg1_type, arg2_type, mt_policy>& m_signal;
1198 	};
1199 
1200 } // namespace sigslot
1201 
1202 #endif // SIGSLOT_H__
1203 
1204