Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

sigslot.h 58.2 KB
Newer Older
schultezub's avatar
schultezub committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*
 
 sigslot.h: Signal/Slot classes
 
 Written by Sarah Thompson (sarah@telergy.com) 2002.
 
 License: Public domain. You are free to use this code however you like,
          with the proviso that the author takes on no responsibility or
          liability for any use.
 
 QUICK DOCUMENTATION
 
 (see also the full documentation at http://sigslot.sourceforge.net/)
 
 1. #define switches

    SIGSLOT_PURE_ISO:
    Define this to force ISO C++ compliance. This also disables
    all of the thread safety support on platforms where it is 
    available.
 
    SIGSLOT_USE_POSIX_THREADS:
    Force use of Posix threads when using a C++ compiler other than
    gcc on a platform that supports Posix threads. (When using gcc,
    this is the default - use SIGSLOT_PURE_ISO to disable this if 
    necessary)
 
    SIGSLOT_DEFAULT_MT_POLICY:
    Where thread support is enabled, this defaults to multi_threaded_global.
    Otherwise, the default is single_threaded. #define this yourself to
    override the default. In pure ISO mode, anything other than
    single_threaded will cause a compiler error.

 2. PLATFORM NOTES
 
    Win32:
    On Win32, the WIN32 symbol must be #defined. Most mainstream
    compilers do this by default, but you may need to define it
    yourself if your build environment is less standard. This causes
    the Win32 thread support to be compiled in and used automatically.
 
    Unix/Linux/BSD, etc:
    If you're using gcc, it is assumed that you have Posix threads
    available, so they are used automatically. You can override this
    (as under Windows) with the SIGSLOT_PURE_ISO switch. If you're using
    something other than gcc but still want to use Posix threads, you
    need to #define SIGSLOT_USE_POSIX_THREADS.
 
    ISO C++:
    If none of the supported platforms are detected, or if
    SIGSLOT_PURE_ISO is defined, all multithreading support is turned off,
    along with any code that might cause a pure ISO C++ environment to
    complain. Before you ask, gcc -ansi -pedantic won't compile this 
    library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of
    errors that aren't really there. If you feel like investigating this,
    please contact the author.
      
 THREADING MODES
 
    single_threaded:
    Your program is assumed to be single threaded from the point of view
    of signal/slot usage (i.e. all objects using signals and slots are
    created and destroyed from a single thread). Behaviour if objects are
    destroyed concurrently is undefined (i.e. you'll get the occasional
    segmentation fault/memory exception).
 
    multi_threaded_global:
    Your program is assumed to be multi threaded. Objects using signals and
    slots can be safely created and destroyed from any thread, even when
    connections exist. In multi_threaded_global mode, this is achieved by a
    single global mutex (actually a critical section on Windows because they
    are faster). This option uses less OS resources, but results in more
    opportunities for contention, possibly resulting in more context switches
    than are strictly necessary.
 
    multi_threaded_local:
    Behaviour in this mode is essentially the same as multi_threaded_global,
    except that each signal, and each object that inherits has_slots, all 
    have their own mutex/critical section. In practice, this means that
    mutex collisions (and hence context switches) only happen if they are
    absolutely essential. However, on some platforms, creating a lot of 
    mutexes can slow down the whole OS, so use this option with care.
 
 USING THE LIBRARY
 
 See the full documentation at http://sigslot.sourceforge.net/
 
*/
schultezub's avatar
schultezub committed
89

schultezub's avatar
schultezub committed
90
91
#ifndef SIGSLOT_H
#define SIGSLOT_H
schultezub's avatar
schultezub committed
92
93
94

#include <set>
#include <list>
95
96
97

#include <tbb/compat/condition_variable>
#include <tbb/concurrent_queue.h>
98
#include <tbb/spin_rw_mutex.h>
schultezub's avatar
schultezub committed
99

100
101
102
#include "ext/tgt/runnable.h"
#include "ext/tgt/singleton.h"

schultezub's avatar
schultezub committed
103
104
105
106
107
108
109
110
111
112
#ifndef SIGSLOT_DEFAULT_MT_POLICY
#	ifdef _SIGSLOT_SINGLE_THREADED
#		define SIGSLOT_DEFAULT_MT_POLICY single_threaded
#	else
#		define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local
#	endif
#endif

namespace sigslot {

113
114
115
116
117
118
    class _signal_handle_base {
    public:
        virtual ~_signal_handle_base() {};
        virtual void emitSignal() const = 0;
    };

119
120
// ================================================================================================

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
    class signal_manager : public tgt::Singleton<signal_manager>, public tgt::Runnable {
        friend class tgt::Singleton<signal_manager>;

    public:
        /**
         * Directly dispatches the signal \a signal to all currently registered listeners.
         * \note    For using threaded signal dispatching use queueSignal()
         * \param   signal   signal to dispatch
         */
        void triggerSignal(_signal_handle_base* signal) const;

        /**
         * Enqueue \a signal into the list of signals to be dispatched.
         * \note    Dispatch will be perfomed in signal_mananger thread. For direct dispatch in
         *          caller thread use triggerSignal().
         * \param   signal   signal to dispatch
         * \return  True, if \a signal was successfully enqueued to signal queue.
         */
        bool queueSignal(_signal_handle_base* signal);

        /// \see Runnable:run
        virtual void run();
        /// \see Runnable:stop
        virtual void stop();

    private:
        /// Private constructor only for singleton
        signal_manager();
        /// Private destructor only for singleton
        ~signal_manager();

        typedef tbb::concurrent_queue<_signal_handle_base*> SignalQueue;

        SignalQueue _signalQueue;   ///< Queue for signals to be dispatched

        std::condition_variable _evaluationCondition; ///< conditional wait to be used when there are currently no jobs to process
        tbb::mutex _ecMutex; ///< Mutex for protecting _evaluationCondition

        static const std::string loggerCat_;
    };

162
163
// ================================================================================================

164
    typedef tbb::spin_rw_mutex tbb_mutex;
schultezub's avatar
schultezub committed
165
166
167
168
169
170
171

    // The multi threading policies only get compiled in if they are enabled.
    class multi_threaded_global
    {
    public:
        multi_threaded_global()
        {
172
            ;
schultezub's avatar
schultezub committed
173
174
175
176
177
178
179
180
181
182
183
184
        }

        multi_threaded_global(const multi_threaded_global&)
        {
            ;
        }

        virtual ~multi_threaded_global()
        {
            ;
        }

185
        tbb_mutex& get_mutex()
schultezub's avatar
schultezub committed
186
        {
187
188
            static tbb_mutex g_mutex;
            return g_mutex;
schultezub's avatar
schultezub committed
189
190
191
192
193
194
195
196
        }
    };

    class multi_threaded_local
    {
    public:
        multi_threaded_local()
        {
197
            ;
schultezub's avatar
schultezub committed
198
199
200
201
202
203
204
        }

        multi_threaded_local(const multi_threaded_local&)
        {
            ;
        }

205
        virtual ~multi_threaded_local()
schultezub's avatar
schultezub committed
206
207
208
209
        {
            ;
        }

210
        tbb_mutex& get_mutex() { return m_mutex; }
schultezub's avatar
schultezub committed
211
212

    private:
213
        tbb_mutex m_mutex;
schultezub's avatar
schultezub committed
214
    };
215
216
217
    
    template<class mt_policy>
    class lock_block_write : tbb_mutex::scoped_lock
schultezub's avatar
schultezub committed
218
219
    {
    public:
220
        lock_block_write(mt_policy *mtx) : tbb_mutex::scoped_lock(mtx->get_mutex(), true)
schultezub's avatar
schultezub committed
221
222
        {
        }
223
224
        
        ~lock_block_write()
schultezub's avatar
schultezub committed
225
226
227
228
        {
        }
    };

229
230
    template<class mt_policy>
    class lock_block_read : tbb_mutex::scoped_lock
schultezub's avatar
schultezub committed
231
232
    {
    public:
233
        lock_block_read(mt_policy *mtx) : tbb_mutex::scoped_lock(mtx->get_mutex(), false)
schultezub's avatar
schultezub committed
234
235
236
        {
        }

237
        ~lock_block_read()
schultezub's avatar
schultezub committed
238
239
240
241
        {
        }
    };

242
// ================================================================================================
243

schultezub's avatar
schultezub committed
244
245
    template<class mt_policy>
    class has_slots;
schultezub's avatar
schultezub committed
246
    
schultezub's avatar
schultezub committed
247
248
249
250
    template<class mt_policy>
    class _connection_base0
    {
    public:
schultezub's avatar
schultezub committed
251
        virtual ~_connection_base0() {}
schultezub's avatar
schultezub committed
252
253
254
255
256
        virtual has_slots<mt_policy>* getdest() const = 0;
        virtual void emitSignal() = 0;
        virtual _connection_base0* clone() = 0;
        virtual _connection_base0* duplicate(has_slots<mt_policy>* pnewdest) = 0;
    };
schultezub's avatar
schultezub committed
257
    
schultezub's avatar
schultezub committed
258
259
260
261
    template<class arg1_type, class mt_policy>
    class _connection_base1
    {
    public:
schultezub's avatar
schultezub committed
262
        virtual ~_connection_base1() {}
schultezub's avatar
schultezub committed
263
264
265
266
267
        virtual has_slots<mt_policy>* getdest() const = 0;
        virtual void emitSignal(arg1_type) = 0;
        virtual _connection_base1<arg1_type, mt_policy>* clone() = 0;
        virtual _connection_base1<arg1_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
    };
schultezub's avatar
schultezub committed
268
    
schultezub's avatar
schultezub committed
269
270
271
272
    template<class arg1_type, class arg2_type, class mt_policy>
    class _connection_base2
    {
    public:
schultezub's avatar
schultezub committed
273
        virtual ~_connection_base2() {}
schultezub's avatar
schultezub committed
274
275
276
277
278
        virtual has_slots<mt_policy>* getdest() const = 0;
        virtual void emitSignal(arg1_type, arg2_type) = 0;
        virtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone() = 0;
        virtual _connection_base2<arg1_type, arg2_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
    };
schultezub's avatar
schultezub committed
279
    
schultezub's avatar
schultezub committed
280
281
282
283
    template<class arg1_type, class arg2_type, class arg3_type, class mt_policy>
    class _connection_base3
    {
    public:
schultezub's avatar
schultezub committed
284
        virtual ~_connection_base3() {}
schultezub's avatar
schultezub committed
285
286
287
288
289
        virtual has_slots<mt_policy>* getdest() const = 0;
        virtual void emitSignal(arg1_type, arg2_type, arg3_type) = 0;
        virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* clone() = 0;
        virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
    };
schultezub's avatar
schultezub committed
290
    
schultezub's avatar
schultezub committed
291
292
293
294
    template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy>
    class _connection_base4
    {
    public:
schultezub's avatar
schultezub committed
295
        virtual ~_connection_base4() {}
schultezub's avatar
schultezub committed
296
297
298
299
300
        virtual has_slots<mt_policy>* getdest() const = 0;
        virtual void emitSignal(arg1_type, arg2_type, arg3_type, arg4_type) = 0;
        virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* clone() = 0;
        virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
    };
schultezub's avatar
schultezub committed
301
    
schultezub's avatar
schultezub committed
302
303
304
305
306
    template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
    class arg5_type, class mt_policy>
    class _connection_base5
    {
    public:
schultezub's avatar
schultezub committed
307
        virtual ~_connection_base5() {}
schultezub's avatar
schultezub committed
308
        virtual has_slots<mt_policy>* getdest() const = 0;
309
310
311
        virtual void emitSignal(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type) = 0;
        virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, mt_policy>* clone() = 0;
        virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
schultezub's avatar
schultezub committed
312
    };
schultezub's avatar
schultezub committed
313
    
314
// ================================================================================================
schultezub's avatar
schultezub committed
315
    
schultezub's avatar
schultezub committed
316
317
318
319
320
    template<class mt_policy>
    class _signal_base : public mt_policy
    {
    public:
        virtual void slot_disconnect(has_slots<mt_policy>* pslot) = 0;
schultezub's avatar
schultezub committed
321
        virtual void slot_duplicate(has_slots<mt_policy> const* poldslot, has_slots<mt_policy>* pnewslot) = 0;
schultezub's avatar
schultezub committed
322
    };
schultezub's avatar
schultezub committed
323
    
schultezub's avatar
schultezub committed
324
325
326
327
    template<class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
    class has_slots : public mt_policy 
    {
    private:
schultezub's avatar
schultezub committed
328
        typedef typename std::set<_signal_base<mt_policy> *> sender_set;
schultezub's avatar
schultezub committed
329
        typedef typename sender_set::const_iterator const_iterator;
schultezub's avatar
schultezub committed
330
        
schultezub's avatar
schultezub committed
331
    public:
schultezub's avatar
schultezub committed
332
333
334
        has_slots() {}
        
        has_slots(has_slots const& hs) : mt_policy(hs)
schultezub's avatar
schultezub committed
335
        {
336
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
337
338
            const_iterator it = hs.m_senders.begin();
            const_iterator itEnd = hs.m_senders.end();
schultezub's avatar
schultezub committed
339
340
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
341
342
343
344
345
                (*it)->slot_duplicate(&hs, this);
                m_senders.insert(*it);
                ++it;
            }
        } 
schultezub's avatar
schultezub committed
346
        
schultezub's avatar
schultezub committed
347
348
        void signal_connect(_signal_base<mt_policy>* sender)
        {
349
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
350
351
            m_senders.insert(sender);
        }
schultezub's avatar
schultezub committed
352
        
schultezub's avatar
schultezub committed
353
354
        void signal_disconnect(_signal_base<mt_policy>* sender)
        {
355
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
356
357
            m_senders.erase(sender);
        }
schultezub's avatar
schultezub committed
358
        
schultezub's avatar
schultezub committed
359
360
361
362
        virtual ~has_slots()
        {
            disconnect_all();
        }
schultezub's avatar
schultezub committed
363
        
schultezub's avatar
schultezub committed
364
365
        void disconnect_all()
        {
366
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
367
368
            const_iterator it = m_senders.begin();
            const_iterator itEnd = m_senders.end();
schultezub's avatar
schultezub committed
369
370
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
371
372
373
                (*it)->slot_disconnect(this);
                ++it;
            }
schultezub's avatar
schultezub committed
374
            
schultezub's avatar
schultezub committed
375
376
            m_senders.erase(m_senders.begin(), m_senders.end());
        }
schultezub's avatar
schultezub committed
377
        
schultezub's avatar
schultezub committed
378
379
380
    private:
        sender_set m_senders;
    };
schultezub's avatar
schultezub committed
381
    
schultezub's avatar
schultezub committed
382
383
384
385
386
    template<class mt_policy>
    class _signal_base0 : public _signal_base<mt_policy>
    {
    public:
        typedef std::list<_connection_base0<mt_policy> *>  connections_list;
schultezub's avatar
schultezub committed
387
388
389
390
        
        _signal_base0() {}
        
        _signal_base0(_signal_base0 const& s) : _signal_base<mt_policy>(s)
schultezub's avatar
schultezub committed
391
        {
392
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
393
394
395
396
            typename connections_list::const_iterator it = s.m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
397
398
399
400
401
                (*it)->getdest()->signal_connect(this);
                m_connected_slots.push_back((*it)->clone());
                ++it;
            }
        }
schultezub's avatar
schultezub committed
402
        
schultezub's avatar
schultezub committed
403
404
405
406
        ~_signal_base0()
        {
            disconnect_all();
        }
schultezub's avatar
schultezub committed
407
        
schultezub's avatar
schultezub committed
408
409
        void disconnect_all()
        {
410
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
411
412
413
414
            typename connections_list::const_iterator it = m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
415
416
417
418
                (*it)->getdest()->signal_disconnect(this);
                delete *it;
                ++it;
            }
schultezub's avatar
schultezub committed
419
            
schultezub's avatar
schultezub committed
420
421
            m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
        }
schultezub's avatar
schultezub committed
422
        
schultezub's avatar
schultezub committed
423
424
        void disconnect(has_slots<mt_policy>* pclass)
        {
425
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
426
427
428
429
430
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                if ((*it)->getdest() == pclass) {
schultezub's avatar
schultezub committed
431
432
433
434
435
                    delete *it;
                    m_connected_slots.erase(it);
                    pclass->signal_disconnect(this);
                    return;
                }
schultezub's avatar
schultezub committed
436
                
schultezub's avatar
schultezub committed
437
438
439
                ++it;
            }
        }
schultezub's avatar
schultezub committed
440
        
schultezub's avatar
schultezub committed
441
442
        void slot_disconnect(has_slots<mt_policy>* pslot)
        {
443
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
444
445
446
447
448
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                typename connections_list::iterator itNext = it;
schultezub's avatar
schultezub committed
449
                ++itNext;
schultezub's avatar
schultezub committed
450
451
                
                if ((*it)->getdest() == pslot) {
schultezub's avatar
schultezub committed
452
                    m_connected_slots.erase(it);
schultezub's avatar
schultezub committed
453
                    //          delete *it;
schultezub's avatar
schultezub committed
454
                }
schultezub's avatar
schultezub committed
455
                
schultezub's avatar
schultezub committed
456
457
458
                it = itNext;
            }
        }
schultezub's avatar
schultezub committed
459
460
        
        void slot_duplicate(has_slots<mt_policy> const* oldtarget, has_slots<mt_policy>* newtarget)
schultezub's avatar
schultezub committed
461
        {
462
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
463
464
465
466
467
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                if ((*it)->getdest() == oldtarget) {
schultezub's avatar
schultezub committed
468
469
                    m_connected_slots.push_back((*it)->duplicate(newtarget));
                }
schultezub's avatar
schultezub committed
470
                
schultezub's avatar
schultezub committed
471
472
473
                ++it;
            }
        }
474
475
476
477
478

        bool has_connections() const
        {
            return !m_connected_slots.empty();
        }
schultezub's avatar
schultezub committed
479
        
schultezub's avatar
schultezub committed
480
481
482
    protected:
        connections_list m_connected_slots;   
    };
schultezub's avatar
schultezub committed
483
    
schultezub's avatar
schultezub committed
484
485
486
487
488
    template<class arg1_type, class mt_policy>
    class _signal_base1 : public _signal_base<mt_policy>
    {
    public:
        typedef std::list<_connection_base1<arg1_type, mt_policy> *>  connections_list;
schultezub's avatar
schultezub committed
489
490
491
492
        
        _signal_base1() {}
        
        _signal_base1(_signal_base1<arg1_type, mt_policy> const& s) : _signal_base<mt_policy>(s)
schultezub's avatar
schultezub committed
493
        {
494
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
495
496
497
498
            typename connections_list::const_iterator it = s.m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
499
500
501
502
503
                (*it)->getdest()->signal_connect(this);
                m_connected_slots.push_back((*it)->clone());
                ++it;
            }
        }
schultezub's avatar
schultezub committed
504
505
        
        void slot_duplicate(has_slots<mt_policy> const* oldtarget, has_slots<mt_policy>* newtarget)
schultezub's avatar
schultezub committed
506
        {
507
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
508
509
510
511
512
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                if ((*it)->getdest() == oldtarget) {
schultezub's avatar
schultezub committed
513
514
                    m_connected_slots.push_back((*it)->duplicate(newtarget));
                }
schultezub's avatar
schultezub committed
515
                
schultezub's avatar
schultezub committed
516
517
518
                ++it;
            }
        }
schultezub's avatar
schultezub committed
519
        
schultezub's avatar
schultezub committed
520
521
522
523
        ~_signal_base1()
        {
            disconnect_all();
        }
schultezub's avatar
schultezub committed
524
        
schultezub's avatar
schultezub committed
525
526
        void disconnect_all()
        {
527
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
528
529
530
531
            typename connections_list::const_iterator it = m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
532
533
534
535
                (*it)->getdest()->signal_disconnect(this);
                delete *it;
                ++it;
            }
schultezub's avatar
schultezub committed
536
            
schultezub's avatar
schultezub committed
537
538
            m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
        }
schultezub's avatar
schultezub committed
539
        
schultezub's avatar
schultezub committed
540
541
        void disconnect(has_slots<mt_policy>* pclass)
        {
542
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
543
544
545
546
547
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                if ((*it)->getdest() == pclass) {
schultezub's avatar
schultezub committed
548
549
550
551
552
                    delete *it;
                    m_connected_slots.erase(it);
                    pclass->signal_disconnect(this);
                    return;
                }
schultezub's avatar
schultezub committed
553
                
schultezub's avatar
schultezub committed
554
555
556
                ++it;
            }
        }
schultezub's avatar
schultezub committed
557
        
schultezub's avatar
schultezub committed
558
559
        void slot_disconnect(has_slots<mt_policy>* pslot)
        {
560
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
561
562
563
564
565
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                typename connections_list::iterator itNext = it;
schultezub's avatar
schultezub committed
566
                ++itNext;
schultezub's avatar
schultezub committed
567
568
                
                if ((*it)->getdest() == pslot) {
schultezub's avatar
schultezub committed
569
                    m_connected_slots.erase(it);
schultezub's avatar
schultezub committed
570
                    //          delete *it;
schultezub's avatar
schultezub committed
571
                }
schultezub's avatar
schultezub committed
572
                
schultezub's avatar
schultezub committed
573
574
575
                it = itNext;
            }
        }
576
577
578
579
580

        bool has_connections() const
        {
            return !m_connected_slots.empty();
        }
schultezub's avatar
schultezub committed
581
582
        
        
schultezub's avatar
schultezub committed
583
584
585
    protected:
        connections_list m_connected_slots;   
    };
schultezub's avatar
schultezub committed
586
    
schultezub's avatar
schultezub committed
587
588
589
590
591
    template<class arg1_type, class arg2_type, class mt_policy>
    class _signal_base2 : public _signal_base<mt_policy>
    {
    public:
        typedef std::list<_connection_base2<arg1_type, arg2_type, mt_policy> *>
schultezub's avatar
schultezub committed
592
593
594
595
596
        connections_list;
        
        _signal_base2() {}
        
        _signal_base2(_signal_base2<arg1_type, arg2_type, mt_policy> const& s) : _signal_base<mt_policy>(s)
schultezub's avatar
schultezub committed
597
        {
598
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
599
600
601
602
            typename connections_list::const_iterator it = s.m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
603
604
605
606
607
                (*it)->getdest()->signal_connect(this);
                m_connected_slots.push_back((*it)->clone());
                ++it;
            }
        }
schultezub's avatar
schultezub committed
608
609
        
        void slot_duplicate(has_slots<mt_policy> const* oldtarget, has_slots<mt_policy>* newtarget)
schultezub's avatar
schultezub committed
610
        {
611
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
612
613
614
615
616
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                if ((*it)->getdest() == oldtarget) {
schultezub's avatar
schultezub committed
617
618
                    m_connected_slots.push_back((*it)->duplicate(newtarget));
                }
schultezub's avatar
schultezub committed
619
                
schultezub's avatar
schultezub committed
620
621
622
                ++it;
            }
        }
schultezub's avatar
schultezub committed
623
        
schultezub's avatar
schultezub committed
624
625
626
627
        ~_signal_base2()
        {
            disconnect_all();
        }
schultezub's avatar
schultezub committed
628
        
schultezub's avatar
schultezub committed
629
630
        void disconnect_all()
        {
631
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
632
633
634
635
            typename connections_list::const_iterator it = m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
636
637
638
639
                (*it)->getdest()->signal_disconnect(this);
                delete *it;
                ++it;
            }
schultezub's avatar
schultezub committed
640
            
schultezub's avatar
schultezub committed
641
642
            m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
        }
schultezub's avatar
schultezub committed
643
        
schultezub's avatar
schultezub committed
644
645
        void disconnect(has_slots<mt_policy>* pclass)
        {
646
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
647
648
649
650
651
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                if ((*it)->getdest() == pclass) {
schultezub's avatar
schultezub committed
652
653
654
655
656
                    delete *it;
                    m_connected_slots.erase(it);
                    pclass->signal_disconnect(this);
                    return;
                }
schultezub's avatar
schultezub committed
657
                
schultezub's avatar
schultezub committed
658
659
660
                ++it;
            }
        }
schultezub's avatar
schultezub committed
661
        
schultezub's avatar
schultezub committed
662
663
        void slot_disconnect(has_slots<mt_policy>* pslot)
        {
664
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
665
666
667
668
669
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                typename connections_list::iterator itNext = it;
schultezub's avatar
schultezub committed
670
                ++itNext;
schultezub's avatar
schultezub committed
671
672
                
                if ((*it)->getdest() == pslot) {
schultezub's avatar
schultezub committed
673
                    m_connected_slots.erase(it);
schultezub's avatar
schultezub committed
674
                    //          delete *it;
schultezub's avatar
schultezub committed
675
                }
schultezub's avatar
schultezub committed
676
                
schultezub's avatar
schultezub committed
677
678
679
                it = itNext;
            }
        }
680
681
682
683
684

        bool has_connections() const
        {
            return !m_connected_slots.empty();
        }
schultezub's avatar
schultezub committed
685
        
schultezub's avatar
schultezub committed
686
687
688
    protected:
        connections_list m_connected_slots;   
    };
schultezub's avatar
schultezub committed
689
    
schultezub's avatar
schultezub committed
690
691
692
693
694
    template<class arg1_type, class arg2_type, class arg3_type, class mt_policy>
    class _signal_base3 : public _signal_base<mt_policy>
    {
    public:
        typedef std::list<_connection_base3<arg1_type, arg2_type, arg3_type, mt_policy> *>
schultezub's avatar
schultezub committed
695
696
697
698
699
700
701
        connections_list;
        
        _signal_base3() {}
        
        _signal_base3(_signal_base3<arg1_type, arg2_type, arg3_type, mt_policy> const& s)
        : _signal_base<mt_policy>(s)
        {
702
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
703
704
705
706
            typename connections_list::const_iterator it = s.m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
707
708
709
710
711
                (*it)->getdest()->signal_connect(this);
                m_connected_slots.push_back((*it)->clone());
                ++it;
            }
        }
schultezub's avatar
schultezub committed
712
713
        
        void slot_duplicate(has_slots<mt_policy> const* oldtarget, has_slots<mt_policy>* newtarget)
schultezub's avatar
schultezub committed
714
        {
715
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
716
717
718
719
720
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                if ((*it)->getdest() == oldtarget) {
schultezub's avatar
schultezub committed
721
722
                    m_connected_slots.push_back((*it)->duplicate(newtarget));
                }
schultezub's avatar
schultezub committed
723
                
schultezub's avatar
schultezub committed
724
725
726
                ++it;
            }
        }
schultezub's avatar
schultezub committed
727
        
schultezub's avatar
schultezub committed
728
729
730
731
        ~_signal_base3()
        {
            disconnect_all();
        }
schultezub's avatar
schultezub committed
732
        
schultezub's avatar
schultezub committed
733
734
        void disconnect_all()
        {
735
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
736
737
738
739
            typename connections_list::const_iterator it = m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
740
741
742
743
                (*it)->getdest()->signal_disconnect(this);
                delete *it;
                ++it;
            }
schultezub's avatar
schultezub committed
744
            
schultezub's avatar
schultezub committed
745
746
            m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
        }
schultezub's avatar
schultezub committed
747
        
schultezub's avatar
schultezub committed
748
749
        void disconnect(has_slots<mt_policy>* pclass)
        {
750
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
751
752
753
754
755
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                if ((*it)->getdest() == pclass) {
schultezub's avatar
schultezub committed
756
757
758
759
760
                    delete *it;
                    m_connected_slots.erase(it);
                    pclass->signal_disconnect(this);
                    return;
                }
schultezub's avatar
schultezub committed
761
                
schultezub's avatar
schultezub committed
762
763
764
                ++it;
            }
        }
schultezub's avatar
schultezub committed
765
        
schultezub's avatar
schultezub committed
766
767
        void slot_disconnect(has_slots<mt_policy>* pslot)
        {
768
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
769
770
771
772
773
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                typename connections_list::iterator itNext = it;
schultezub's avatar
schultezub committed
774
                ++itNext;
schultezub's avatar
schultezub committed
775
776
                
                if ((*it)->getdest() == pslot) {
schultezub's avatar
schultezub committed
777
                    m_connected_slots.erase(it);
schultezub's avatar
schultezub committed
778
                    //          delete *it;
schultezub's avatar
schultezub committed
779
                }
schultezub's avatar
schultezub committed
780
                
schultezub's avatar
schultezub committed
781
782
783
                it = itNext;
            }
        }
784
785
786
787
788

        bool has_connections() const
        {
            return !m_connected_slots.empty();
        }
schultezub's avatar
schultezub committed
789
        
schultezub's avatar
schultezub committed
790
791
792
    protected:
        connections_list m_connected_slots;   
    };
schultezub's avatar
schultezub committed
793
    
schultezub's avatar
schultezub committed
794
795
796
797
798
    template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy>
    class _signal_base4 : public _signal_base<mt_policy>
    {
    public:
        typedef std::list<_connection_base4<arg1_type, arg2_type, arg3_type,
schultezub's avatar
schultezub committed
799
800
801
802
        arg4_type, mt_policy> *>  connections_list;
        
        _signal_base4() {}
        
schultezub's avatar
schultezub committed
803
        _signal_base4(const _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>& s)
schultezub's avatar
schultezub committed
804
        : _signal_base<mt_policy>(s)
schultezub's avatar
schultezub committed
805
        {
806
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
807
808
809
810
            typename connections_list::const_iterator it = s.m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
811
812
                (*it)->getdest()->signal_connect(this);
                m_connected_slots.push_back((*it)->clone());
schultezub's avatar
schultezub committed
813
                
schultezub's avatar
schultezub committed
814
815
816
                ++it;
            }
        }
schultezub's avatar
schultezub committed
817
        
schultezub's avatar
schultezub committed
818
819
        void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
        {
820
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
821
822
823
824
825
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                if ((*it)->getdest() == oldtarget) {
schultezub's avatar
schultezub committed
826
827
                    m_connected_slots.push_back((*it)->duplicate(newtarget));
                }
schultezub's avatar
schultezub committed
828
                
schultezub's avatar
schultezub committed
829
830
831
                ++it;
            }
        }
schultezub's avatar
schultezub committed
832
        
schultezub's avatar
schultezub committed
833
834
835
836
        ~_signal_base4()
        {
            disconnect_all();
        }
schultezub's avatar
schultezub committed
837
        
schultezub's avatar
schultezub committed
838
839
        void disconnect_all()
        {
840
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
841
842
843
844
            typename connections_list::const_iterator it = m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
845
846
                (*it)->getdest()->signal_disconnect(this);
                delete *it;
schultezub's avatar
schultezub committed
847
                
schultezub's avatar
schultezub committed
848
849
                ++it;
            }
schultezub's avatar
schultezub committed
850
            
schultezub's avatar
schultezub committed
851
852
            m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
        }
schultezub's avatar
schultezub committed
853
        
schultezub's avatar
schultezub committed
854
855
        void disconnect(has_slots<mt_policy>* pclass)
        {
856
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
857
858
859
860
861
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                if ((*it)->getdest() == pclass) {
schultezub's avatar
schultezub committed
862
863
864
865
866
                    delete *it;
                    m_connected_slots.erase(it);
                    pclass->signal_disconnect(this);
                    return;
                }
schultezub's avatar
schultezub committed
867
                
schultezub's avatar
schultezub committed
868
869
870
                ++it;
            }
        }
schultezub's avatar
schultezub committed
871
        
schultezub's avatar
schultezub committed
872
873
        void slot_disconnect(has_slots<mt_policy>* pslot)
        {
874
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
875
876
877
878
879
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                typename connections_list::iterator itNext = it;
schultezub's avatar
schultezub committed
880
                ++itNext;
schultezub's avatar
schultezub committed
881
882
                
                if ((*it)->getdest() == pslot) {
schultezub's avatar
schultezub committed
883
                    m_connected_slots.erase(it);
schultezub's avatar
schultezub committed
884
                    //          delete *it;
schultezub's avatar
schultezub committed
885
                }
schultezub's avatar
schultezub committed
886
                
schultezub's avatar
schultezub committed
887
888
889
                it = itNext;
            }
        }
890
891
892
893
894

        bool has_connections() const
        {
            return !m_connected_slots.empty();
        }
schultezub's avatar
schultezub committed
895
        
schultezub's avatar
schultezub committed
896
897
898
    protected:
        connections_list m_connected_slots;   
    };
schultezub's avatar
schultezub committed
899
    
900
    template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class arg5_type, class mt_policy>
schultezub's avatar
schultezub committed
901
902
903
    class _signal_base5 : public _signal_base<mt_policy>
    {
    public:
904
        typedef std::list<_connection_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, mt_policy> *>  connections_list;
schultezub's avatar
schultezub committed
905
906
907
        
        _signal_base5() {}
        
908
        _signal_base5(const _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, mt_policy>& s)
schultezub's avatar
schultezub committed
909
        : _signal_base<mt_policy>(s)
schultezub's avatar
schultezub committed
910
        {
911
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
912
913
914
915
            typename connections_list::const_iterator it = s.m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
916
917
                (*it)->getdest()->signal_connect(this);
                m_connected_slots.push_back((*it)->clone());
schultezub's avatar
schultezub committed
918
                
schultezub's avatar
schultezub committed
919
920
921
                ++it;
            }
        }
schultezub's avatar
schultezub committed
922
        
schultezub's avatar
schultezub committed
923
924
        void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
        {
925
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
926
927
928
929
930
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                if ((*it)->getdest() == oldtarget) {
schultezub's avatar
schultezub committed
931
932
                    m_connected_slots.push_back((*it)->duplicate(newtarget));
                }
schultezub's avatar
schultezub committed
933
                
schultezub's avatar
schultezub committed
934
935
936
                ++it;
            }
        }
schultezub's avatar
schultezub committed
937
        
schultezub's avatar
schultezub committed
938
939
940
941
        ~_signal_base5()
        {
            disconnect_all();
        }
schultezub's avatar
schultezub committed
942
        
schultezub's avatar
schultezub committed
943
944
        void disconnect_all()
        {
945
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
946
947
948
949
            typename connections_list::const_iterator it = m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
950
951
                (*it)->getdest()->signal_disconnect(this);
                delete *it;
schultezub's avatar
schultezub committed
952
                
schultezub's avatar
schultezub committed
953
954
                ++it;
            }
schultezub's avatar
schultezub committed
955
            
schultezub's avatar
schultezub committed
956
957
            m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
        }
schultezub's avatar
schultezub committed
958
        
schultezub's avatar
schultezub committed
959
960
        void disconnect(has_slots<mt_policy>* pclass)
        {
961
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
962
963
964
965
966
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                if ((*it)->getdest() == pclass) {
schultezub's avatar
schultezub committed
967
968
969
970
971
                    delete *it;
                    m_connected_slots.erase(it);
                    pclass->signal_disconnect(this);
                    return;
                }
schultezub's avatar
schultezub committed
972
                
schultezub's avatar
schultezub committed
973
974
975
                ++it;
            }
        }
schultezub's avatar
schultezub committed
976
        
schultezub's avatar
schultezub committed
977
978
        void slot_disconnect(has_slots<mt_policy>* pslot)
        {
979
            lock_block_write<mt_policy> lock(this);
schultezub's avatar
schultezub committed
980
981
982
983
984
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
            
            while (it != itEnd) {
                typename connections_list::iterator itNext = it;
schultezub's avatar
schultezub committed
985
                ++itNext;
schultezub's avatar
schultezub committed
986
987
                
                if ((*it)->getdest() == pslot) {
schultezub's avatar
schultezub committed
988
                    m_connected_slots.erase(it);
schultezub's avatar
schultezub committed
989
                    //          delete *it;
schultezub's avatar
schultezub committed
990
                }
schultezub's avatar
schultezub committed
991
                
schultezub's avatar
schultezub committed
992
993
994
                it = itNext;
            }
        }
995
996
997
998
999

        bool has_connections() const
        {
            return !m_connected_slots.empty();
        }
schultezub's avatar
schultezub committed
1000
        
schultezub's avatar
schultezub committed
1001
1002
1003
    protected:
        connections_list m_connected_slots;   
    };
schultezub's avatar
schultezub committed
1004
    
1005
1006
1007
1008
// ================================================================================================

    template<class dest_type, class mt_policy>
    class _connection0 : public _connection_base0<mt_policy>
schultezub's avatar
schultezub committed
1009
1010
    {
    public:
1011
        _connection0()
schultezub's avatar
schultezub committed
1012
        {
1013
1014
            m_pobject = 0;
            m_pmemfun = 0;
schultezub's avatar
schultezub committed
1015
        }
schultezub's avatar
schultezub committed
1016
        
1017
        _connection0(dest_type* pobject, void (dest_type::*pmemfun)())
schultezub's avatar
schultezub committed
1018
        {
1019
1020
            m_pobject = pobject;
            m_pmemfun = pmemfun;
schultezub's avatar
schultezub committed
1021
        }
schultezub's avatar
schultezub committed
1022
        
1023
        virtual _connection_base0<mt_policy>* clone()
schultezub's avatar
schultezub committed
1024
        {
1025
            return new _connection0<dest_type, mt_policy>(*this);
schultezub's avatar
schultezub committed
1026
        }
schultezub's avatar
schultezub committed
1027
        
1028
        virtual _connection_base0<mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
schultezub's avatar
schultezub committed
1029
        {
1030
            return new _connection0<dest_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
schultezub's avatar
schultezub committed
1031
        }
schultezub's avatar
schultezub committed
1032
        
1033
        virtual void emitSignal()
schultezub's avatar
schultezub committed
1034
        {
1035
            (m_pobject->*m_pmemfun)();
schultezub's avatar
schultezub committed
1036
        }
schultezub's avatar
schultezub committed
1037
        
1038
        virtual has_slots<mt_policy>* getdest() const
1039
        {
1040
            return m_pobject;
1041
        }
schultezub's avatar
schultezub committed
1042
        
1043
1044
1045
    private:
        dest_type* m_pobject;
        void (dest_type::* m_pmemfun)();