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.8 KB
Newer Older
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
// ================================================================================================
// 
// sigslot.h/sigslot.cpp - Signal/Slot classes:
// 
// Original siglsot implementation written by Sarah Thompson (sarah@telergy.com) 2002 and 
// published under public domain. <http://sigslot.sourceforge.net/>
// 
// This version of the sigslot library is heavily modified, C++ compliant, inherently thread-safe,
// and offers a manager class that allows to queue and asynchronously dispatch signals.
// 
// Copyright (C) 2012-2014, all rights reserved,
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
//      Chair for Computer Aided Medical Procedures
//      Technische Universität München
//      Boltzmannstr. 3, 85748 Garching b. München, Germany
// 
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 
// except in compliance with the License. You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software distributed under the 
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
// either express or implied. See the License for the specific language governing permissions 
// and limitations under the License.
// 
// ================================================================================================
schultezub's avatar
schultezub committed
28

schultezub's avatar
schultezub committed
29
30
#ifndef SIGSLOT_H
#define SIGSLOT_H
schultezub's avatar
schultezub committed
31

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

#ifdef CAMPVIS_DYNAMIC_LIBS
    #ifdef SIGSLOT_BUILD_DLL
        // building library -> export symbols
        #ifdef WIN32
            #define SIGSLOT_API __declspec(dllexport)
        #else
            #define SIGSLOT_API
        #endif
    #else
        // including library -> import symbols
        #ifdef WIN32
            #define SIGSLOT_API __declspec(dllimport)
        #else
            #define SIGSLOT_API
        #endif
    #endif
#else
    // building/including static library -> do nothing
    #define SIGSLOT_API
#endif


schultezub's avatar
schultezub committed
55
56
#include <set>
#include <list>
57

58
#include "tgt/assert.h"
59
#include <ext/threading.h>
60
#include <tbb/concurrent_queue.h>
61
#include <tbb/concurrent_vector.h>
schultezub's avatar
schultezub committed
62

63
64
65
#include "ext/tgt/runnable.h"
#include "ext/tgt/singleton.h"

schultezub's avatar
schultezub committed
66
namespace sigslot {
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
    
    /**
     * List-like container allowing thread-safe bidirectional iteration, insertion and removal of elements. 
     * ATTENTION: Since removed items are internally stored as nullptr, the element type is constrained 
     * to be a pointer type (or at least have pointer semantics) and never be 0. Use with caution!
     */
    template<typename T>
    class concurrent_pointer_list {
    public:
        /// Typedef for internal storage of elements
        typedef tbb::concurrent_vector<T*> StorageType;

        /// Iterator for concurrent_pointer_list
        class concurrent_pointer_list_iterator : public std::iterator<std::bidirectional_iterator_tag, T*> {
        public:
            concurrent_pointer_list_iterator() {};

            concurrent_pointer_list_iterator(StorageType& storage, typename StorageType::iterator position)
                : _begin(storage.begin())
                , _position(position)
                , _end(storage.end())
            {
                if (_position != _end && *_position == nullptr)
                    operator++();
            }

            concurrent_pointer_list_iterator& operator++() {
                do {
                    ++_position;
96
                } while (_position < _end && *_position == nullptr);
97
98
99
100
101
102
103
104
105
106
107
108
                return *this;
            }

            concurrent_pointer_list_iterator operator++(int) {
                concurrent_pointer_list_iterator toReturn = *this;
                operator++();
                return toReturn;
            }

            concurrent_pointer_list_iterator& operator--() {
                do {
                    --_position;
109
                } while (_position > _begin && *_position == nullptr);
110
111
112
113
114
115
116
117
118
                return *this;
            }

            concurrent_pointer_list_iterator operator--(int) {
                concurrent_pointer_list_iterator toReturn = *this;
                operator--();
                return toReturn;
            }

119
            T*& operator*() const {
120
121
122
                return *_position;
            }

123
            T* operator->() const {
124
125
126
127
                return &*_position;
            }

            bool operator==(const concurrent_pointer_list_iterator& rhs) const {
128
                return (_position == rhs._position);
129
130
131
            }

            bool operator!=(const concurrent_pointer_list_iterator& rhs) const {
132
                return (_position != rhs._position);
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
162
163
164
165
166
167
168
169
170
171
172
173
174
            }

        protected:
            typename StorageType::iterator _begin;
            typename StorageType::iterator _position;
            typename StorageType::iterator _end;
        };

        // TODO: As I am currently too lazy to correctly implement const_iterator: I hacked this collection to have a standard iterator as const_iterator.
        typedef concurrent_pointer_list_iterator iterator; ///< iterator typedef
        typedef concurrent_pointer_list_iterator const_iterator; ///< const_iterator typedef 

        /**
         * Creates a new concurrent_pointer_list object of default size
         */
        concurrent_pointer_list() {};

        /**
         * Creates a new concurrent_pointer_list object of default size
         * \param   initalSize  Initial size fo the internal storage
         */
        concurrent_pointer_list(typename StorageType::size_type initalSize) 
            : _storage(initalSize)
        {};


        /// Return an iterator to the beginning of the collection
        iterator begin() { return iterator(_storage, _storage.begin()); };
        /// Return an iterator to the beginning of the collection
        const_iterator begin() const { 
            StorageType& s = const_cast<StorageType&>(_storage);  // const_cast neccessary, because we did not implement const_iterator
            return const_iterator(s, s.begin()); 
        };

        /// Return an iterator to the end of the collection
        iterator end() { return iterator(_storage, _storage.end()); };
        /// Return an iterator to the end of the collection
        const_iterator end() const  { 
            StorageType& s = const_cast<StorageType&>(_storage);  // const_cast neccessary, because we did not implement const_iterator
            return const_iterator(s, s.end()); 
        };

175
176
        void push_back(T* element) { insert(element); };
        void insert(T* element);
177
178
179
180
181

        size_t erase(T* element);
        void erase(const const_iterator& it) { *it = nullptr; };
        void erase(const const_iterator& begin, const const_iterator& end);

182
        bool empty() const;
183
184
185
186
187
188

    protected:
        StorageType _storage;
    };

// ================================================================================================
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

    template<typename T>
    void concurrent_pointer_list<T>::insert(T* element) {
        iterator it = begin();
        iterator itEnd = end();

        // to ensure non-degrading performance, we first fill the gaps.
        for (/* nothing here */; it != itEnd; ++it) {
            if (*it == nullptr) {
                *it = element;
                return;
            }
        }

        // we did not find an empty element -> we add a new one at the end
        _storage.push_back(element);
    }

207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
    template<typename T>
    size_t concurrent_pointer_list<T>::erase(T* element) {
        size_t count = 0;
        iterator it = begin();
        iterator itEnd = end();

        for (/* nothing here */; it != itEnd; ++it) {
            if (*it == element) {
                *it = nullptr;
                ++count;
            }
        }

        return count;
    }

    template<typename T>
    void concurrent_pointer_list<T>::erase(const typename concurrent_pointer_list<T>::const_iterator& begin, const typename concurrent_pointer_list<T>::const_iterator& end) {
        for (const_iterator it = begin; it != end; ++it) {
            *it = nullptr;
        }
    }

230
231
232
233
234
235
236
237
238
239
240
241
242
243
    template<typename T>
    bool sigslot::concurrent_pointer_list<T>::empty() const {
        iterator it = begin();
        iterator itEnd = end();

        for (/* nothing here */; it != itEnd; ++it) {
            if (*it != nullptr) {
                return false;
            }
        }

        return true;
    }

244
// ================================================================================================
schultezub's avatar
schultezub committed
245

246
    /// Base class for signal handles that provides an interface to emit the signal.
247
248
    class _signal_handle_base {
    public:
249
        /// Virtual destructor
250
        virtual ~_signal_handle_base() {};
251
        /// Emits the signal of this signal handle.
252
253
254
        virtual void emitSignal() const = 0;
    };

255
256
// ================================================================================================

257
258
259
260
261
262
263
264
265
266
267
268
269
    /**
     * Singleton class that takes care of queuing and asynchronously dispatching signals.
     * 
     * The signal_manager implements the Runnable interface, i.e. runs in it's own thread once it
     * was launched. The signal_manager takes care of dispatching signals to their connections.
     * This is either done synchrnously by using triggerSignal() or asynchronously by using 
     * queueSignal(). Furthermore it allows to check, whether the current thread is the 
     * signal_manager thread. This allows the default signal emitting method operator() to 
     * automatically decide on the dispatch type based on the emitting thread.
     * 
     * signal_manager can be considered as thread-safe.
     */
    class SIGSLOT_API signal_manager : public tgt::Singleton<signal_manager>, public tgt::Runnable {
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
        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);

289
290
291
292
293
294
        /**
         * Checks whether calling thread is signal_manager thread.
         * \return  std::this_thread::get_id() == _this_thread_id
         */
        bool isCurrentThreadSignalManagerThread() const;

295
296
297
298
299
300
301
302
303
304
305
        /// \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();

306
        /// Typedef for the signal queue
307
308
        typedef tbb::concurrent_queue<_signal_handle_base*> SignalQueue;

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

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

314
315
        std::thread::id _this_thread_id;

316
317
318
        static const std::string loggerCat_;
    };

319
320
// ================================================================================================

321
    
322
    class SIGSLOT_API has_slots;
schultezub's avatar
schultezub committed
323
    
324
    
325
    class SIGSLOT_API _connection_base0
schultezub's avatar
schultezub committed
326
327
    {
    public:
schultezub's avatar
schultezub committed
328
        virtual ~_connection_base0() {}
329
        virtual has_slots* getdest() const = 0;
schultezub's avatar
schultezub committed
330
331
        virtual void emitSignal() = 0;
        virtual _connection_base0* clone() = 0;
332
        virtual _connection_base0* duplicate(has_slots* pnewdest) = 0;
schultezub's avatar
schultezub committed
333
    };
schultezub's avatar
schultezub committed
334
    
335
    template<class arg1_type>
schultezub's avatar
schultezub committed
336
337
338
    class _connection_base1
    {
    public:
schultezub's avatar
schultezub committed
339
        virtual ~_connection_base1() {}
340
        virtual has_slots* getdest() const = 0;
schultezub's avatar
schultezub committed
341
        virtual void emitSignal(arg1_type) = 0;
342
343
        virtual _connection_base1<arg1_type>* clone() = 0;
        virtual _connection_base1<arg1_type>* duplicate(has_slots* pnewdest) = 0;
schultezub's avatar
schultezub committed
344
    };
schultezub's avatar
schultezub committed
345
    
346
    template<class arg1_type, class arg2_type>
schultezub's avatar
schultezub committed
347
348
349
    class _connection_base2
    {
    public:
schultezub's avatar
schultezub committed
350
        virtual ~_connection_base2() {}
351
        virtual has_slots* getdest() const = 0;
schultezub's avatar
schultezub committed
352
        virtual void emitSignal(arg1_type, arg2_type) = 0;
353
354
        virtual _connection_base2<arg1_type, arg2_type>* clone() = 0;
        virtual _connection_base2<arg1_type, arg2_type>* duplicate(has_slots* pnewdest) = 0;
schultezub's avatar
schultezub committed
355
    };
schultezub's avatar
schultezub committed
356
    
357
    template<class arg1_type, class arg2_type, class arg3_type>
schultezub's avatar
schultezub committed
358
359
360
    class _connection_base3
    {
    public:
schultezub's avatar
schultezub committed
361
        virtual ~_connection_base3() {}
362
        virtual has_slots* getdest() const = 0;
schultezub's avatar
schultezub committed
363
        virtual void emitSignal(arg1_type, arg2_type, arg3_type) = 0;
364
365
        virtual _connection_base3<arg1_type, arg2_type, arg3_type>* clone() = 0;
        virtual _connection_base3<arg1_type, arg2_type, arg3_type>* duplicate(has_slots* pnewdest) = 0;
schultezub's avatar
schultezub committed
366
    };
schultezub's avatar
schultezub committed
367
    
368
    template<class arg1_type, class arg2_type, class arg3_type, class arg4_type>
schultezub's avatar
schultezub committed
369
370
371
    class _connection_base4
    {
    public:
schultezub's avatar
schultezub committed
372
        virtual ~_connection_base4() {}
373
        virtual has_slots* getdest() const = 0;
schultezub's avatar
schultezub committed
374
        virtual void emitSignal(arg1_type, arg2_type, arg3_type, arg4_type) = 0;
375
376
        virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type>* clone() = 0;
        virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type>* duplicate(has_slots* pnewdest) = 0;
schultezub's avatar
schultezub committed
377
    };
schultezub's avatar
schultezub committed
378
    
379
    template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class arg5_type>
schultezub's avatar
schultezub committed
380
381
382
    class _connection_base5
    {
    public:
schultezub's avatar
schultezub committed
383
        virtual ~_connection_base5() {}
384
        virtual has_slots* getdest() const = 0;
385
        virtual void emitSignal(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type) = 0;
386
387
        virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type>* clone() = 0;
        virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type>* duplicate(has_slots* pnewdest) = 0;
schultezub's avatar
schultezub committed
388
    };
schultezub's avatar
schultezub committed
389
    
390
// ================================================================================================
schultezub's avatar
schultezub committed
391
    
392
    
393
    class SIGSLOT_API _signal_base
schultezub's avatar
schultezub committed
394
395
    {
    public:
396
397
        virtual void slot_disconnect(has_slots* pslot) = 0;
        virtual void slot_duplicate(has_slots const* poldslot, has_slots* pnewslot) = 0;
schultezub's avatar
schultezub committed
398
    };
schultezub's avatar
schultezub committed
399
    
400
    class SIGSLOT_API has_slots
schultezub's avatar
schultezub committed
401
402
    {
    private:
403
404
        typedef concurrent_pointer_list<_signal_base> sender_set;
        typedef sender_set::const_iterator const_iterator;
schultezub's avatar
schultezub committed
405
        
schultezub's avatar
schultezub committed
406
    public:
schultezub's avatar
schultezub committed
407
408
        has_slots() {}
        
409
        has_slots(has_slots const& hs)
schultezub's avatar
schultezub committed
410
411
412
        {
            const_iterator it = hs.m_senders.begin();
            const_iterator itEnd = hs.m_senders.end();
schultezub's avatar
schultezub committed
413
414
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
415
416
417
418
419
                (*it)->slot_duplicate(&hs, this);
                m_senders.insert(*it);
                ++it;
            }
        } 
schultezub's avatar
schultezub committed
420
        
421
        void signal_connect(_signal_base* sender)
schultezub's avatar
schultezub committed
422
423
424
        {
            m_senders.insert(sender);
        }
schultezub's avatar
schultezub committed
425
        
426
        void signal_disconnect(_signal_base* sender)
schultezub's avatar
schultezub committed
427
428
429
        {
            m_senders.erase(sender);
        }
schultezub's avatar
schultezub committed
430
        
schultezub's avatar
schultezub committed
431
432
433
434
        virtual ~has_slots()
        {
            disconnect_all();
        }
schultezub's avatar
schultezub committed
435
        
schultezub's avatar
schultezub committed
436
437
438
439
        void disconnect_all()
        {
            const_iterator it = m_senders.begin();
            const_iterator itEnd = m_senders.end();
schultezub's avatar
schultezub committed
440
441
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
442
443
444
                (*it)->slot_disconnect(this);
                ++it;
            }
schultezub's avatar
schultezub committed
445
            
schultezub's avatar
schultezub committed
446
447
            m_senders.erase(m_senders.begin(), m_senders.end());
        }
schultezub's avatar
schultezub committed
448
        
schultezub's avatar
schultezub committed
449
450
451
    private:
        sender_set m_senders;
    };
schultezub's avatar
schultezub committed
452
    
453
454
    
    class _signal_base0 : public _signal_base
schultezub's avatar
schultezub committed
455
456
    {
    public:
457
        typedef concurrent_pointer_list<_connection_base0 >  connections_list;
schultezub's avatar
schultezub committed
458
459
460
        
        _signal_base0() {}
        
461
        _signal_base0(_signal_base0 const& s) : _signal_base(s)
schultezub's avatar
schultezub committed
462
        {
463
464
            connections_list::const_iterator it = s.m_connected_slots.begin();
            connections_list::const_iterator itEnd = s.m_connected_slots.end();
schultezub's avatar
schultezub committed
465
466
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
467
468
469
470
471
                (*it)->getdest()->signal_connect(this);
                m_connected_slots.push_back((*it)->clone());
                ++it;
            }
        }
schultezub's avatar
schultezub committed
472
        
schultezub's avatar
schultezub committed
473
474
475
476
        ~_signal_base0()
        {
            disconnect_all();
        }
schultezub's avatar
schultezub committed
477
        
schultezub's avatar
schultezub committed
478
479
        void disconnect_all()
        {
480
481
            connections_list::const_iterator it = m_connected_slots.begin();
            connections_list::const_iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
482
483
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
484
485
486
487
                (*it)->getdest()->signal_disconnect(this);
                delete *it;
                ++it;
            }
schultezub's avatar
schultezub committed
488
            
schultezub's avatar
schultezub committed
489
490
            m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
        }
schultezub's avatar
schultezub committed
491
        
492
        void disconnect(has_slots* pclass)
schultezub's avatar
schultezub committed
493
        {
494
495
            connections_list::iterator it = m_connected_slots.begin();
            connections_list::iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
496
497
498
            
            while (it != itEnd) {
                if ((*it)->getdest() == pclass) {
schultezub's avatar
schultezub committed
499
500
501
502
503
                    delete *it;
                    m_connected_slots.erase(it);
                    pclass->signal_disconnect(this);
                    return;
                }
schultezub's avatar
schultezub committed
504
                
schultezub's avatar
schultezub committed
505
506
507
                ++it;
            }
        }
schultezub's avatar
schultezub committed
508
        
509
        void slot_disconnect(has_slots* pslot)
schultezub's avatar
schultezub committed
510
        {
511
512
            connections_list::iterator it = m_connected_slots.begin();
            connections_list::iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
513
514
            
            while (it != itEnd) {
515
                connections_list::iterator itNext = it;
schultezub's avatar
schultezub committed
516
                ++itNext;
schultezub's avatar
schultezub committed
517
518
                
                if ((*it)->getdest() == pslot) {
schultezub's avatar
schultezub committed
519
                    m_connected_slots.erase(it);
schultezub's avatar
schultezub committed
520
                    //          delete *it;
schultezub's avatar
schultezub committed
521
                }
schultezub's avatar
schultezub committed
522
                
schultezub's avatar
schultezub committed
523
524
525
                it = itNext;
            }
        }
schultezub's avatar
schultezub committed
526
        
527
        void slot_duplicate(has_slots const* oldtarget, has_slots* newtarget)
schultezub's avatar
schultezub committed
528
        {
529
530
            connections_list::iterator it = m_connected_slots.begin();
            connections_list::iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
531
532
533
            
            while (it != itEnd) {
                if ((*it)->getdest() == oldtarget) {
schultezub's avatar
schultezub committed
534
535
                    m_connected_slots.push_back((*it)->duplicate(newtarget));
                }
schultezub's avatar
schultezub committed
536
                
schultezub's avatar
schultezub committed
537
538
539
                ++it;
            }
        }
540
541
542
543
544

        bool has_connections() const
        {
            return !m_connected_slots.empty();
        }
schultezub's avatar
schultezub committed
545
        
schultezub's avatar
schultezub committed
546
547
548
    protected:
        connections_list m_connected_slots;   
    };
schultezub's avatar
schultezub committed
549
    
550
551
    template<class arg1_type>
    class _signal_base1 : public _signal_base
schultezub's avatar
schultezub committed
552
553
    {
    public:
554
        typedef concurrent_pointer_list<_connection_base1<arg1_type> >  connections_list;
schultezub's avatar
schultezub committed
555
556
557
        
        _signal_base1() {}
        
558
        _signal_base1(_signal_base1<arg1_type> const& s) : _signal_base(s)
schultezub's avatar
schultezub committed
559
        {
560
561
            typename connections_list::const_iterator it = s.m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
schultezub's avatar
schultezub committed
562
563
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
564
565
566
567
568
                (*it)->getdest()->signal_connect(this);
                m_connected_slots.push_back((*it)->clone());
                ++it;
            }
        }
schultezub's avatar
schultezub committed
569
        
570
        void slot_duplicate(has_slots const* oldtarget, has_slots* newtarget)
schultezub's avatar
schultezub committed
571
        {
572
573
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
574
575
576
            
            while (it != itEnd) {
                if ((*it)->getdest() == oldtarget) {
schultezub's avatar
schultezub committed
577
578
                    m_connected_slots.push_back((*it)->duplicate(newtarget));
                }
schultezub's avatar
schultezub committed
579
                
schultezub's avatar
schultezub committed
580
581
582
                ++it;
            }
        }
schultezub's avatar
schultezub committed
583
        
schultezub's avatar
schultezub committed
584
585
586
587
        ~_signal_base1()
        {
            disconnect_all();
        }
schultezub's avatar
schultezub committed
588
        
schultezub's avatar
schultezub committed
589
590
        void disconnect_all()
        {
591
592
            typename connections_list::const_iterator it = m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
593
594
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
595
596
597
598
                (*it)->getdest()->signal_disconnect(this);
                delete *it;
                ++it;
            }
schultezub's avatar
schultezub committed
599
            
schultezub's avatar
schultezub committed
600
601
            m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
        }
schultezub's avatar
schultezub committed
602
        
603
        void disconnect(has_slots* pclass)
schultezub's avatar
schultezub committed
604
        {
605
606
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
607
608
609
            
            while (it != itEnd) {
                if ((*it)->getdest() == pclass) {
schultezub's avatar
schultezub committed
610
611
612
613
614
                    delete *it;
                    m_connected_slots.erase(it);
                    pclass->signal_disconnect(this);
                    return;
                }
schultezub's avatar
schultezub committed
615
                
schultezub's avatar
schultezub committed
616
617
618
                ++it;
            }
        }
schultezub's avatar
schultezub committed
619
        
620
        void slot_disconnect(has_slots* pslot)
schultezub's avatar
schultezub committed
621
        {
622
623
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
624
625
            
            while (it != itEnd) {
626
                typename connections_list::iterator itNext = it;
schultezub's avatar
schultezub committed
627
                ++itNext;
schultezub's avatar
schultezub committed
628
629
                
                if ((*it)->getdest() == pslot) {
schultezub's avatar
schultezub committed
630
                    m_connected_slots.erase(it);
schultezub's avatar
schultezub committed
631
                    //          delete *it;
schultezub's avatar
schultezub committed
632
                }
schultezub's avatar
schultezub committed
633
                
schultezub's avatar
schultezub committed
634
635
636
                it = itNext;
            }
        }
637
638
639
640
641

        bool has_connections() const
        {
            return !m_connected_slots.empty();
        }
schultezub's avatar
schultezub committed
642
643
        
        
schultezub's avatar
schultezub committed
644
645
646
    protected:
        connections_list m_connected_slots;   
    };
schultezub's avatar
schultezub committed
647
    
648
649
    template<class arg1_type, class arg2_type>
    class _signal_base2 : public _signal_base
schultezub's avatar
schultezub committed
650
651
    {
    public:
652
        typedef concurrent_pointer_list<_connection_base2<arg1_type, arg2_type> >  connections_list;
schultezub's avatar
schultezub committed
653
654
655
        
        _signal_base2() {}
        
656
        _signal_base2(_signal_base2<arg1_type, arg2_type> const& s) : _signal_base(s)
schultezub's avatar
schultezub committed
657
        {
658
659
            typename connections_list::const_iterator it = s.m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
schultezub's avatar
schultezub committed
660
661
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
662
663
664
665
666
                (*it)->getdest()->signal_connect(this);
                m_connected_slots.push_back((*it)->clone());
                ++it;
            }
        }
schultezub's avatar
schultezub committed
667
        
668
        void slot_duplicate(has_slots const* oldtarget, has_slots* newtarget)
schultezub's avatar
schultezub committed
669
        {
670
671
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
672
673
674
            
            while (it != itEnd) {
                if ((*it)->getdest() == oldtarget) {
schultezub's avatar
schultezub committed
675
676
                    m_connected_slots.push_back((*it)->duplicate(newtarget));
                }
schultezub's avatar
schultezub committed
677
                
schultezub's avatar
schultezub committed
678
679
680
                ++it;
            }
        }
schultezub's avatar
schultezub committed
681
        
schultezub's avatar
schultezub committed
682
683
684
685
        ~_signal_base2()
        {
            disconnect_all();
        }
schultezub's avatar
schultezub committed
686
        
schultezub's avatar
schultezub committed
687
688
        void disconnect_all()
        {
689
690
            typename connections_list::const_iterator it = m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
691
692
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
693
694
695
696
                (*it)->getdest()->signal_disconnect(this);
                delete *it;
                ++it;
            }
schultezub's avatar
schultezub committed
697
            
schultezub's avatar
schultezub committed
698
699
            m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
        }
schultezub's avatar
schultezub committed
700
        
701
        void disconnect(has_slots* pclass)
schultezub's avatar
schultezub committed
702
        {
703
704
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
705
706
707
            
            while (it != itEnd) {
                if ((*it)->getdest() == pclass) {
schultezub's avatar
schultezub committed
708
709
710
711
712
                    delete *it;
                    m_connected_slots.erase(it);
                    pclass->signal_disconnect(this);
                    return;
                }
schultezub's avatar
schultezub committed
713
                
schultezub's avatar
schultezub committed
714
715
716
                ++it;
            }
        }
schultezub's avatar
schultezub committed
717
        
718
        void slot_disconnect(has_slots* pslot)
schultezub's avatar
schultezub committed
719
        {
720
721
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
722
723
            
            while (it != itEnd) {
724
                typename connections_list::iterator itNext = it;
schultezub's avatar
schultezub committed
725
                ++itNext;
schultezub's avatar
schultezub committed
726
727
                
                if ((*it)->getdest() == pslot) {
schultezub's avatar
schultezub committed
728
                    m_connected_slots.erase(it);
schultezub's avatar
schultezub committed
729
                    //          delete *it;
schultezub's avatar
schultezub committed
730
                }
schultezub's avatar
schultezub committed
731
                
schultezub's avatar
schultezub committed
732
733
734
                it = itNext;
            }
        }
735
736
737
738
739

        bool has_connections() const
        {
            return !m_connected_slots.empty();
        }
schultezub's avatar
schultezub committed
740
        
schultezub's avatar
schultezub committed
741
742
743
    protected:
        connections_list m_connected_slots;   
    };
schultezub's avatar
schultezub committed
744
    
745
746
    template<class arg1_type, class arg2_type, class arg3_type>
    class _signal_base3 : public _signal_base
schultezub's avatar
schultezub committed
747
748
    {
    public:
749
750
        typedef concurrent_pointer_list<_connection_base3<arg1_type, arg2_type, arg3_type> >  connections_list;
         
schultezub's avatar
schultezub committed
751
752
        _signal_base3() {}
        
753
754
        _signal_base3(_signal_base3<arg1_type, arg2_type, arg3_type> const& s)
        : _signal_base(s)
schultezub's avatar
schultezub committed
755
        {
756
757
            typename connections_list::const_iterator it = s.m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
schultezub's avatar
schultezub committed
758
759
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
760
761
762
763
764
                (*it)->getdest()->signal_connect(this);
                m_connected_slots.push_back((*it)->clone());
                ++it;
            }
        }
schultezub's avatar
schultezub committed
765
        
766
        void slot_duplicate(has_slots const* oldtarget, has_slots* newtarget)
schultezub's avatar
schultezub committed
767
        {
768
769
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
770
771
772
            
            while (it != itEnd) {
                if ((*it)->getdest() == oldtarget) {
schultezub's avatar
schultezub committed
773
774
                    m_connected_slots.push_back((*it)->duplicate(newtarget));
                }
schultezub's avatar
schultezub committed
775
                
schultezub's avatar
schultezub committed
776
777
778
                ++it;
            }
        }
schultezub's avatar
schultezub committed
779
        
schultezub's avatar
schultezub committed
780
781
782
783
        ~_signal_base3()
        {
            disconnect_all();
        }
schultezub's avatar
schultezub committed
784
        
schultezub's avatar
schultezub committed
785
786
        void disconnect_all()
        {
787
788
            typename connections_list::const_iterator it = m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
789
790
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
791
792
793
794
                (*it)->getdest()->signal_disconnect(this);
                delete *it;
                ++it;
            }
schultezub's avatar
schultezub committed
795
            
schultezub's avatar
schultezub committed
796
797
            m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
        }
schultezub's avatar
schultezub committed
798
        
799
        void disconnect(has_slots* pclass)
schultezub's avatar
schultezub committed
800
        {
801
802
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
803
804
805
            
            while (it != itEnd) {
                if ((*it)->getdest() == pclass) {
schultezub's avatar
schultezub committed
806
807
808
809
810
                    delete *it;
                    m_connected_slots.erase(it);
                    pclass->signal_disconnect(this);
                    return;
                }
schultezub's avatar
schultezub committed
811
                
schultezub's avatar
schultezub committed
812
813
814
                ++it;
            }
        }
schultezub's avatar
schultezub committed
815
        
816
        void slot_disconnect(has_slots* pslot)
schultezub's avatar
schultezub committed
817
        {
818
819
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
820
821
            
            while (it != itEnd) {
822
                typename connections_list::iterator itNext = it;
schultezub's avatar
schultezub committed
823
                ++itNext;
schultezub's avatar
schultezub committed
824
825
                
                if ((*it)->getdest() == pslot) {
schultezub's avatar
schultezub committed
826
                    m_connected_slots.erase(it);
schultezub's avatar
schultezub committed
827
                    //          delete *it;
schultezub's avatar
schultezub committed
828
                }
schultezub's avatar
schultezub committed
829
                
schultezub's avatar
schultezub committed
830
831
832
                it = itNext;
            }
        }
833
834
835
836
837

        bool has_connections() const
        {
            return !m_connected_slots.empty();
        }
schultezub's avatar
schultezub committed
838
        
schultezub's avatar
schultezub committed
839
840
841
    protected:
        connections_list m_connected_slots;   
    };
schultezub's avatar
schultezub committed
842
    
843
844
    template<class arg1_type, class arg2_type, class arg3_type, class arg4_type>
    class _signal_base4 : public _signal_base
schultezub's avatar
schultezub committed
845
846
    {
    public:
847
        typedef concurrent_pointer_list<_connection_base4<arg1_type, arg2_type, arg3_type, arg4_type> >  connections_list;
schultezub's avatar
schultezub committed
848
849
850
        
        _signal_base4() {}
        
851
852
        _signal_base4(const _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type>& s)
        : _signal_base(s)
schultezub's avatar
schultezub committed
853
        {
854
855
            typename connections_list::const_iterator it = s.m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
schultezub's avatar
schultezub committed
856
857
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
858
859
                (*it)->getdest()->signal_connect(this);
                m_connected_slots.push_back((*it)->clone());
schultezub's avatar
schultezub committed
860
                
schultezub's avatar
schultezub committed
861
862
863
                ++it;
            }
        }
schultezub's avatar
schultezub committed
864
        
865
        void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget)
schultezub's avatar
schultezub committed
866
        {
867
868
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
869
870
871
            
            while (it != itEnd) {
                if ((*it)->getdest() == oldtarget) {
schultezub's avatar
schultezub committed
872
873
                    m_connected_slots.push_back((*it)->duplicate(newtarget));
                }
schultezub's avatar
schultezub committed
874
                
schultezub's avatar
schultezub committed
875
876
877
                ++it;
            }
        }
schultezub's avatar
schultezub committed
878
        
schultezub's avatar
schultezub committed
879
880
881
882
        ~_signal_base4()
        {
            disconnect_all();
        }
schultezub's avatar
schultezub committed
883
        
schultezub's avatar
schultezub committed
884
885
        void disconnect_all()
        {
886
887
            typename connections_list::const_iterator it = m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
888
889
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
890
891
                (*it)->getdest()->signal_disconnect(this);
                delete *it;
schultezub's avatar
schultezub committed
892
                
schultezub's avatar
schultezub committed
893
894
                ++it;
            }
schultezub's avatar
schultezub committed
895
            
schultezub's avatar
schultezub committed
896
897
            m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
        }
schultezub's avatar
schultezub committed
898
        
899
        void disconnect(has_slots* pclass)
schultezub's avatar
schultezub committed
900
        {
901
902
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
903
904
905
            
            while (it != itEnd) {
                if ((*it)->getdest() == pclass) {
schultezub's avatar
schultezub committed
906
907
908
909
910
                    delete *it;
                    m_connected_slots.erase(it);
                    pclass->signal_disconnect(this);
                    return;
                }
schultezub's avatar
schultezub committed
911
                
schultezub's avatar
schultezub committed
912
913
914
                ++it;
            }
        }
schultezub's avatar
schultezub committed
915
        
916
        void slot_disconnect(has_slots* pslot)
schultezub's avatar
schultezub committed
917
        {
918
919
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
920
921
            
            while (it != itEnd) {
922
                typename connections_list::iterator itNext = it;
schultezub's avatar
schultezub committed
923
                ++itNext;
schultezub's avatar
schultezub committed
924
925
                
                if ((*it)->getdest() == pslot) {
schultezub's avatar
schultezub committed
926
                    m_connected_slots.erase(it);
schultezub's avatar
schultezub committed
927
                    //          delete *it;
schultezub's avatar
schultezub committed
928
                }
schultezub's avatar
schultezub committed
929
                
schultezub's avatar
schultezub committed
930
931
932
                it = itNext;
            }
        }
933
934
935
936
937

        bool has_connections() const
        {
            return !m_connected_slots.empty();
        }
schultezub's avatar
schultezub committed
938
        
schultezub's avatar
schultezub committed
939
940
941
    protected:
        connections_list m_connected_slots;   
    };
schultezub's avatar
schultezub committed
942
    
943
944
    template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class arg5_type>
    class _signal_base5 : public _signal_base
schultezub's avatar
schultezub committed
945
946
    {
    public:
947
        typedef concurrent_pointer_list<_connection_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type> >  connections_list;
schultezub's avatar
schultezub committed
948
949
950
        
        _signal_base5() {}
        
951
952
        _signal_base5(const _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type>& s)
        : _signal_base(s)
schultezub's avatar
schultezub committed
953
        {
954
955
            typename connections_list::const_iterator it = s.m_connected_slots.begin();
            typename connections_list::const_iterator itEnd = s.m_connected_slots.end();
schultezub's avatar
schultezub committed
956
957
            
            while (it != itEnd) {
schultezub's avatar
schultezub committed
958
959
                (*it)->getdest()->signal_connect(this);
                m_connected_slots.push_back((*it)->clone());
schultezub's avatar
schultezub committed
960
                
schultezub's avatar
schultezub committed
961
962
963
                ++it;
            }
        }
schultezub's avatar
schultezub committed
964
        
965
        void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget)
schultezub's avatar
schultezub committed
966
        {
967
968
            typename connections_list::iterator it = m_connected_slots.begin();
            typename connections_list::iterator itEnd = m_connected_slots.end();
schultezub's avatar
schultezub committed
969
970
971
            
            while (it != itEnd) {
                if ((*it)->getdest() == oldtarget) {
schultezub's avatar
schultezub committed
972
973
                    m_connected_slots.push_back((*it)->duplicate(newtarget));
                }
schultezub's avatar
schultezub committed
974
                
schultezub's avatar
schultezub committed
975
976
977
                ++it;
            }
        }
schultezub's avatar
schultezub committed
978
        
schultezub's avatar
schultezub committed
979
980
981
982
        ~_signal_base5()
        {
            disconnect_all();
        }
schultezub's avatar
schultezub committed
983
        
schultezub's avatar
schultezub committed
984
985
        void disconnect_all()
        {
986
987
            typename connections_list