Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(22)

Side by Side Diff: webrtc/base/sigslot.h

Issue 2854533002: Run clang-format on sigslot.h. (Closed)
Patch Set: Merge with master Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // sigslot.h: Signal/Slot classes 1 // sigslot.h: Signal/Slot classes
2 // 2 //
3 // Written by Sarah Thompson (sarah@telergy.com) 2002. 3 // Written by Sarah Thompson (sarah@telergy.com) 2002.
4 // 4 //
5 // License: Public domain. You are free to use this code however you like, with the proviso that 5 // License: Public domain. You are free to use this code however you like, with
6 // the author takes on no responsibility or liability for any use. 6 // the proviso that the author takes on no responsibility or liability for any
7 // use.
7 // 8 //
8 // QUICK DOCUMENTATION 9 // QUICK DOCUMENTATION
9 // 10 //
10 //» » » » (see also the full documentation at http://sigsl ot.sourceforge.net/) 11 // (see also the full documentation at http://sigslot.sourceforge.net/)
11 // 12 //
12 //» » #define switches 13 // #define switches
13 //» » » SIGSLOT_PURE_ISO» » » - Define this to force ISO C++ compliance. This also disables 14 // SIGSLOT_PURE_ISO:
14 //» » » » » » » » » » all of the thread safety support on platforms where it is 15 // Define this to force ISO C++ compliance. This also disables all of
15 //» » » » » » » » » » available. 16 // the thread safety support on platforms where it is available.
16 // 17 //
17 //» » » SIGSLOT_USE_POSIX_THREADS» - Force use of Posix thr eads when using a C++ compiler other than 18 // SIGSLOT_USE_POSIX_THREADS:
18 //» » » » » » » » » » gcc on a platform that supports Posix threads. (When using gcc, 19 // Force use of Posix threads when using a C++ compiler other than gcc
19 //» » » » » » » » » » this is the default - use SIGSLOT_PURE_ISO to disable this if 20 // on a platform that supports Posix threads. (When using gcc, this is
20 //» » » » » » » » » » necessary) 21 // the default - use SIGSLOT_PURE_ISO to disable this if necessary)
21 // 22 //
22 //» » » SIGSLOT_DEFAULT_MT_POLICY» - Where thread support i s enabled, this defaults to multi_threaded_global. 23 // SIGSLOT_DEFAULT_MT_POLICY:
23 //» » » » » » » » » » Otherwise, the default is single_threaded. #define this yourself to 24 // Where thread support is enabled, this defaults to
24 //» » » » » » » » » » override the default. In pure ISO mode, anything other than 25 // multi_threaded_global. Otherwise, the default is single_threaded.
25 //» » » » » » » » » » single_threaded will cause a compiler error. 26 // #define this yourself to override the default. In pure ISO mode,
27 // anything other than single_threaded will cause a compiler error.
26 // 28 //
27 //» » PLATFORM NOTES 29 // PLATFORM NOTES
28 // 30 //
29 //» » » Win32» » » » » » - On Win 32, the WEBRTC_WIN symbol must be #defined. Most mainstream 31 // Win32:
30 //» » » » » » » » » » compilers do this by default, but you may need to define it 32 // On Win32, the WEBRTC_WIN symbol must be #defined. Most mainstream
31 //» » » » » » » » » » yourself if your build environment is less standard. This causes 33 // compilers do this by default, but you may need to define it yourself
32 //» » » » » » » » » » the Win32 thread support to be compiled in and used automatically. 34 // if your build environment is less standard. This causes the Win32
35 // thread support to be compiled in and used automatically.
33 // 36 //
34 //» » » Unix/Linux/BSD, etc.» » - If you're using gcc, i t is assumed that you have Posix threads 37 // Unix/Linux/BSD, etc.:
35 //» » » » » » » » » » available, so they are used automatically. You can override this 38 // If you're using gcc, it is assumed that you have Posix threads
36 //» » » » » » » » » » (as under Windows) with the SIGSLOT_PURE_ISO switch. If you're using 39 // available, so they are used automatically. You can override this (as
37 //» » » » » » » » » » something other than gcc but still want to use Posix threads, you 40 // under Windows) with the SIGSLOT_PURE_ISO switch. If you're using
38 //» » » » » » » » » » need to #define SIGSLOT_USE_POSIX_THREADS. 41 // something other than gcc but still want to use Posix threads, you
42 // need to #define SIGSLOT_USE_POSIX_THREADS.
39 // 43 //
40 //» » » ISO C++»» » » » » - If non e of the supported platforms are detected, or if 44 // ISO C++:
41 //» » » » » » » » » » SIGSLOT_PURE_ISO is defined, all multithreading support is turned off, 45 // If none of the supported platforms are detected, or if
42 //» » » » » » » » » » along with any code that might cause a pure ISO C++ environment to 46 // SIGSLOT_PURE_ISO is defined, all multithreading support is turned
43 //» » » » » » » » » » complain. Before you ask, gcc -ansi -pedantic won't compile this 47 // off, along with any code that might cause a pure ISO C++ environment
44 //» » » » » » » » » » library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of 48 // to complain. Before you ask, gcc -ansi -pedantic won't compile this
45 //» » » » » » » » » » errors that aren't really there. If you feel like investigating this, 49 // library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of
46 //» » » » » » » » » » please contact the author. 50 // errors that aren't really there. If you feel like investigating this,
51 // please contact the author.
47 // 52 //
48 // 53 //
49 //» » THREADING MODES 54 // THREADING MODES
50 // 55 //
51 //» » » single_threaded»» » » - Your program i s assumed to be single threaded from the point of view 56 // single_threaded:
52 //» » » » » » » » » » of signal/slot usage (i.e. all objects using signals and slots are 57 // Your program is assumed to be single threaded from the point of view
53 //» » » » » » » » » » created and destroyed from a single thread). Behaviour if objects are 58 // of signal/slot usage (i.e. all objects using signals and slots are
54 //» » » » » » » » » » destroyed concurrently is undefined (i.e. you'll get the occasional 59 // created and destroyed from a single thread). Behaviour if objects are
55 //» » » » » » » » » » segmentation fault/memory exception). 60 // destroyed concurrently is undefined (i.e. you'll get the occasional
61 // segmentation fault/memory exception).
56 // 62 //
57 //» » » multi_threaded_global» » - Your program is assume d to be multi threaded. Objects using signals and 63 // multi_threaded_global:
58 //» » » » » » » » » » slots can be safely created and destroyed from any thread, even when 64 // Your program is assumed to be multi threaded. Objects using signals
59 //» » » » » » » » » » connections exist. In multi_threaded_global mode, this is achieved by a 65 // and slots can be safely created and destroyed from any thread, even
60 //» » » » » » » » » » single global mutex (actually a critical section on Windows because they 66 // when connections exist. In multi_threaded_global mode, this is
61 //» » » » » » » » » » are faster). This option uses less OS resources, but results in more 67 // achieved by a single global mutex (actually a critical section on
62 //» » » » » » » » » » opportunities for contention, possibly resulting in more context switches 68 // Windows because they are faster). This option uses less OS resources,
63 //» » » » » » » » » » than are strictly necessary. 69 // but results in more opportunities for contention, possibly resulting
70 // in more context switches than are strictly necessary.
64 // 71 //
65 //» » » multi_threaded_local» » - Behaviour in this mode is essentially the same as multi_threaded_global, 72 // multi_threaded_local:
66 //» » » » » » » » » » except that each signal, and each object that inherits has_slots, all 73 // Behaviour in this mode is essentially the same as
67 //» » » » » » » » » » have their own mutex/critical section. In practice, this means that 74 // multi_threaded_global, except that each signal, and each object that
68 //» » » » » » » » » » mutex collisions (and hence context switches) only happen if they are 75 // inherits has_slots, all have their own mutex/critical section. In
69 //» » » » » » » » » » absolutely essential. However, on some platforms, creating a lot of 76 // practice, this means that mutex collisions (and hence context
70 //» » » » » » » » » » mutexes can slow down the whole OS, so use this option with care. 77 // switches) only happen if they are absolutely essential. However, on
78 // some platforms, creating a lot of mutexes can slow down the whole OS,
79 // so use this option with care.
71 // 80 //
72 //» » USING THE LIBRARY 81 // USING THE LIBRARY
73 // 82 //
74 //» » » See the full documentation at http://sigslot.sourceforge .net/ 83 // See the full documentation at http://sigslot.sourceforge.net/
75 //
76 // 84 //
77 // Libjingle specific: 85 // Libjingle specific:
86 //
78 // This file has been modified such that has_slots and signalx do not have to be 87 // This file has been modified such that has_slots and signalx do not have to be
79 // using the same threading requirements. E.g. it is possible to connect a 88 // using the same threading requirements. E.g. it is possible to connect a
80 // has_slots<single_threaded> and signal0<multi_threaded_local> or 89 // has_slots<single_threaded> and signal0<multi_threaded_local> or
81 // has_slots<multi_threaded_local> and signal0<single_threaded>. 90 // has_slots<multi_threaded_local> and signal0<single_threaded>.
82 // If has_slots is single threaded the user must ensure that it is not trying 91 // If has_slots is single threaded the user must ensure that it is not trying
83 // to connect or disconnect to signalx concurrently or data race may occur. 92 // to connect or disconnect to signalx concurrently or data race may occur.
84 // If signalx is single threaded the user must ensure that disconnect, connect 93 // If signalx is single threaded the user must ensure that disconnect, connect
85 // or signal is not happening concurrently or data race may occur. 94 // or signal is not happening concurrently or data race may occur.
86 95
87 #ifndef WEBRTC_BASE_SIGSLOT_H__ 96 #ifndef WEBRTC_BASE_SIGSLOT_H__
88 #define WEBRTC_BASE_SIGSLOT_H__ 97 #define WEBRTC_BASE_SIGSLOT_H__
89 98
99 #include <stdlib.h>
90 #include <cstring> 100 #include <cstring>
91 #include <list> 101 #include <list>
92 #include <set> 102 #include <set>
93 #include <stdlib.h>
94 103
95 // On our copy of sigslot.h, we set single threading as default. 104 // On our copy of sigslot.h, we set single threading as default.
96 #define SIGSLOT_DEFAULT_MT_POLICY single_threaded 105 #define SIGSLOT_DEFAULT_MT_POLICY single_threaded
97 106
98 #if defined(SIGSLOT_PURE_ISO) || (!defined(WEBRTC_WIN) && !defined(__GNUG__) && !defined(SIGSLOT_USE_POSIX_THREADS)) 107 #if defined(SIGSLOT_PURE_ISO) || \
99 #» define _SIGSLOT_SINGLE_THREADED 108 (!defined(WEBRTC_WIN) && !defined(__GNUG__) && \
109 !defined(SIGSLOT_USE_POSIX_THREADS))
110 #define _SIGSLOT_SINGLE_THREADED
100 #elif defined(WEBRTC_WIN) 111 #elif defined(WEBRTC_WIN)
101 #» define _SIGSLOT_HAS_WIN32_THREADS 112 #define _SIGSLOT_HAS_WIN32_THREADS
102 #» if !defined(WIN32_LEAN_AND_MEAN) 113 #if !defined(WIN32_LEAN_AND_MEAN)
103 #» » define WIN32_LEAN_AND_MEAN 114 #define WIN32_LEAN_AND_MEAN
104 #» endif 115 #endif
105 #» include "webrtc/base/win32.h" 116 #include "webrtc/base/win32.h"
106 #elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS) 117 #elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS)
107 #» define _SIGSLOT_HAS_POSIX_THREADS 118 #define _SIGSLOT_HAS_POSIX_THREADS
108 #» include <pthread.h> 119 #include <pthread.h>
109 #else 120 #else
110 #» define _SIGSLOT_SINGLE_THREADED 121 #define _SIGSLOT_SINGLE_THREADED
111 #endif 122 #endif
112 123
113 #ifndef SIGSLOT_DEFAULT_MT_POLICY 124 #ifndef SIGSLOT_DEFAULT_MT_POLICY
114 #» ifdef _SIGSLOT_SINGLE_THREADED 125 #ifdef _SIGSLOT_SINGLE_THREADED
115 #» » define SIGSLOT_DEFAULT_MT_POLICY single_threaded 126 #define SIGSLOT_DEFAULT_MT_POLICY single_threaded
116 #» else 127 #else
117 #» » define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local 128 #define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local
118 #» endif 129 #endif
119 #endif 130 #endif
120 131
121 // TODO: change this namespace to rtc? 132 // TODO: change this namespace to rtc?
122 namespace sigslot { 133 namespace sigslot {
123 134
124 » class single_threaded 135 class single_threaded {
125 » { 136 public:
126 » public: 137 void lock() {}
127 » » void lock() {} 138 void unlock() {}
128 » » void unlock() {} 139 };
129 » };
130 140
131 #ifdef _SIGSLOT_HAS_WIN32_THREADS 141 #ifdef _SIGSLOT_HAS_WIN32_THREADS
132 » // The multi threading policies only get compiled in if they are enabled . 142 // The multi threading policies only get compiled in if they are enabled.
133 » class multi_threaded_global 143 class multi_threaded_global {
134 » { 144 public:
135 » public: 145 multi_threaded_global() {
136 » » multi_threaded_global() 146 static bool isinitialised = false;
137 » » { 147
138 » » » static bool isinitialised = false; 148 if (!isinitialised) {
139 149 InitializeCriticalSection(get_critsec());
140 » » » if(!isinitialised) 150 isinitialised = true;
141 » » » { 151 }
142 » » » » InitializeCriticalSection(get_critsec()); 152 }
143 » » » » isinitialised = true; 153
144 » » » } 154 void lock() { EnterCriticalSection(get_critsec()); }
145 » » } 155
146 156 void unlock() { LeaveCriticalSection(get_critsec()); }
147 » » void lock() 157
148 » » { 158 private:
149 » » » EnterCriticalSection(get_critsec()); 159 CRITICAL_SECTION* get_critsec() {
150 » » } 160 static CRITICAL_SECTION g_critsec;
151 161 return &g_critsec;
152 » » void unlock() 162 }
153 » » { 163 };
154 » » » LeaveCriticalSection(get_critsec()); 164
155 » » } 165 class multi_threaded_local {
156 166 public:
157 » private: 167 multi_threaded_local() { InitializeCriticalSection(&m_critsec); }
158 » » CRITICAL_SECTION* get_critsec() 168
159 » » { 169 multi_threaded_local(const multi_threaded_local&) {
160 » » » static CRITICAL_SECTION g_critsec; 170 InitializeCriticalSection(&m_critsec);
161 » » » return &g_critsec; 171 }
162 » » } 172
163 » }; 173 ~multi_threaded_local() { DeleteCriticalSection(&m_critsec); }
164 174
165 » class multi_threaded_local 175 void lock() { EnterCriticalSection(&m_critsec); }
166 » { 176
167 » public: 177 void unlock() { LeaveCriticalSection(&m_critsec); }
168 » » multi_threaded_local() 178
169 » » { 179 private:
170 » » » InitializeCriticalSection(&m_critsec); 180 CRITICAL_SECTION m_critsec;
171 » » } 181 };
172 182 #endif // _SIGSLOT_HAS_WIN32_THREADS
173 » » multi_threaded_local(const multi_threaded_local&)
174 » » {
175 » » » InitializeCriticalSection(&m_critsec);
176 » » }
177
178 » » ~multi_threaded_local()
179 » » {
180 » » » DeleteCriticalSection(&m_critsec);
181 » » }
182
183 » » void lock()
184 » » {
185 » » » EnterCriticalSection(&m_critsec);
186 » » }
187
188 » » void unlock()
189 » » {
190 » » » LeaveCriticalSection(&m_critsec);
191 » » }
192
193 » private:
194 » » CRITICAL_SECTION m_critsec;
195 » };
196 #endif // _SIGSLOT_HAS_WIN32_THREADS
197 183
198 #ifdef _SIGSLOT_HAS_POSIX_THREADS 184 #ifdef _SIGSLOT_HAS_POSIX_THREADS
199 // The multi threading policies only get compiled in if they are enabled . 185 // The multi threading policies only get compiled in if they are enabled.
200 class multi_threaded_global 186 class multi_threaded_global {
201 { 187 public:
202 public: 188 void lock() { pthread_mutex_lock(get_mutex()); }
203 void lock() 189 void unlock() { pthread_mutex_unlock(get_mutex()); }
204 { 190
205 pthread_mutex_lock(get_mutex()); 191 private:
206 } 192 static pthread_mutex_t* get_mutex();
207 void unlock() 193 };
208 { 194
209 pthread_mutex_unlock(get_mutex()); 195 class multi_threaded_local {
210 } 196 public:
211 197 multi_threaded_local() { pthread_mutex_init(&m_mutex, nullptr); }
212 private: 198 multi_threaded_local(const multi_threaded_local&) {
213 static pthread_mutex_t* get_mutex(); 199 pthread_mutex_init(&m_mutex, nullptr);
214 }; 200 }
215 201 ~multi_threaded_local() { pthread_mutex_destroy(&m_mutex); }
216 class multi_threaded_local 202 void lock() { pthread_mutex_lock(&m_mutex); }
217 { 203 void unlock() { pthread_mutex_unlock(&m_mutex); }
218 public: 204
219 multi_threaded_local() { pthread_mutex_init(&m_mutex, nullptr); } 205 private:
220 multi_threaded_local(const multi_threaded_local&) { 206 pthread_mutex_t m_mutex;
221 pthread_mutex_init(&m_mutex, nullptr); 207 };
222 } 208 #endif // _SIGSLOT_HAS_POSIX_THREADS
223 ~multi_threaded_local() 209
224 { 210 template <class mt_policy>
225 pthread_mutex_destroy(&m_mutex); 211 class lock_block {
226 } 212 public:
227 void lock() 213 mt_policy* m_mutex;
228 { 214
229 pthread_mutex_lock(&m_mutex); 215 lock_block(mt_policy* mtx) : m_mutex(mtx) { m_mutex->lock(); }
230 } 216
231 void unlock() 217 ~lock_block() { m_mutex->unlock(); }
232 { 218 };
233 pthread_mutex_unlock(&m_mutex); 219
234 } 220 class _signal_base_interface;
235 221
236 private: 222 class has_slots_interface {
237 pthread_mutex_t m_mutex; 223 private:
238 }; 224 typedef void (*signal_connect_t)(has_slots_interface* self,
239 #endif // _SIGSLOT_HAS_POSIX_THREADS 225 _signal_base_interface* sender);
240 226 typedef void (*signal_disconnect_t)(has_slots_interface* self,
241 template<class mt_policy> 227 _signal_base_interface* sender);
242 class lock_block 228 typedef void (*disconnect_all_t)(has_slots_interface* self);
243 { 229
244 public: 230 const signal_connect_t m_signal_connect;
245 mt_policy *m_mutex; 231 const signal_disconnect_t m_signal_disconnect;
246 232 const disconnect_all_t m_disconnect_all;
247 lock_block(mt_policy *mtx) 233
248 : m_mutex(mtx) 234 protected:
249 { 235 has_slots_interface(signal_connect_t conn,
250 m_mutex->lock(); 236 signal_disconnect_t disc,
251 } 237 disconnect_all_t disc_all)
252 238 : m_signal_connect(conn),
253 ~lock_block() 239 m_signal_disconnect(disc),
254 { 240 m_disconnect_all(disc_all) {}
255 m_mutex->unlock(); 241
256 } 242 // Doesn't really need to be virtual, but is for backwards compatibility
257 }; 243 // (it was virtual in a previous version of sigslot).
258 244 virtual ~has_slots_interface() {}
259 class _signal_base_interface; 245
260 246 public:
261 class has_slots_interface 247 void signal_connect(_signal_base_interface* sender) {
262 { 248 m_signal_connect(this, sender);
263 private: 249 }
264 typedef void (*signal_connect_t)(has_slots_interface* self, _sig nal_base_interface* sender); 250
265 typedef void (*signal_disconnect_t)(has_slots_interface* self, _ signal_base_interface* sender); 251 void signal_disconnect(_signal_base_interface* sender) {
266 typedef void (*disconnect_all_t)(has_slots_interface* self); 252 m_signal_disconnect(this, sender);
267 253 }
268 const signal_connect_t m_signal_connect; 254
269 const signal_disconnect_t m_signal_disconnect; 255 void disconnect_all() { m_disconnect_all(this); }
270 const disconnect_all_t m_disconnect_all; 256 };
271 257
272 protected: 258 class _signal_base_interface {
273 has_slots_interface(signal_connect_t conn, signal_disconnect_t d isc, disconnect_all_t disc_all) : 259 private:
274 m_signal_connect(conn), m_signal_disconnect(disc), m_dis connect_all(disc_all) 260 typedef void (*slot_disconnect_t)(_signal_base_interface* self,
275 { 261 has_slots_interface* pslot);
276 } 262 typedef void (*slot_duplicate_t)(_signal_base_interface* self,
277 263 const has_slots_interface* poldslot,
278 // Doesn't really need to be virtual, but is for backwards compa tibility 264 has_slots_interface* pnewslot);
279 // (it was virtual in a previous version of sigslot). 265
280 virtual ~has_slots_interface() {} 266 const slot_disconnect_t m_slot_disconnect;
281 267 const slot_duplicate_t m_slot_duplicate;
282 public: 268
283 void signal_connect(_signal_base_interface* sender) 269 protected:
284 { 270 _signal_base_interface(slot_disconnect_t disc, slot_duplicate_t dupl)
285 m_signal_connect(this, sender); 271 : m_slot_disconnect(disc), m_slot_duplicate(dupl) {}
286 } 272
287 273 ~_signal_base_interface() {}
288 void signal_disconnect(_signal_base_interface* sender) 274
289 { 275 public:
290 m_signal_disconnect(this, sender); 276 void slot_disconnect(has_slots_interface* pslot) {
291 } 277 m_slot_disconnect(this, pslot);
292 278 }
293 void disconnect_all() 279
294 { 280 void slot_duplicate(const has_slots_interface* poldslot,
295 m_disconnect_all(this); 281 has_slots_interface* pnewslot) {
296 } 282 m_slot_duplicate(this, poldslot, pnewslot);
297 }; 283 }
298 284 };
299 class _signal_base_interface 285
300 { 286 class _opaque_connection {
301 private: 287 private:
302 typedef void (*slot_disconnect_t)(_signal_base_interface* self, has_slots_interface* pslot); 288 typedef void (*emit_t)(const _opaque_connection*);
303 typedef void (*slot_duplicate_t)(_signal_base_interface* self, c onst has_slots_interface* poldslot, has_slots_interface* pnewslot); 289 template <typename FromT, typename ToT>
304 290 union union_caster {
305 const slot_disconnect_t m_slot_disconnect; 291 FromT from;
306 const slot_duplicate_t m_slot_duplicate; 292 ToT to;
307 293 };
308 protected: 294
309 _signal_base_interface(slot_disconnect_t disc, slot_duplicate_t dupl) : 295 emit_t pemit;
310 m_slot_disconnect(disc), m_slot_duplicate(dupl) 296 has_slots_interface* pdest;
311 { 297 // Pointers to member functions may be up to 16 bytes for virtual classes,
312 } 298 // so make sure we have enough space to store it.
313 299 unsigned char pmethod[16];
314 ~_signal_base_interface() {} 300
315 301 public:
316 public: 302 template <typename DestT, typename... Args>
317 void slot_disconnect(has_slots_interface* pslot) 303 _opaque_connection(DestT* pd, void (DestT::*pm)(Args...)) : pdest(pd) {
318 { 304 typedef void (DestT::*pm_t)(Args...);
319 m_slot_disconnect(this, pslot); 305 static_assert(sizeof(pm_t) <= sizeof(pmethod),
320 } 306 "Size of slot function pointer too large.");
321 307
322 void slot_duplicate(const has_slots_interface* poldslot, has_slo ts_interface* pnewslot) 308 std::memcpy(pmethod, &pm, sizeof(pm_t));
323 { 309
324 m_slot_duplicate(this, poldslot, pnewslot); 310 typedef void (*em_t)(const _opaque_connection* self, Args...);
325 } 311 union_caster<em_t, emit_t> caster2;
326 }; 312 caster2.from = &_opaque_connection::emitter<DestT, Args...>;
327 313 pemit = caster2.to;
328 class _opaque_connection 314 }
329 { 315
330 private: 316 has_slots_interface* getdest() const { return pdest; }
331 typedef void (*emit_t)(const _opaque_connection*); 317
332 template< typename FromT, typename ToT > 318 _opaque_connection duplicate(has_slots_interface* newtarget) const {
333 union union_caster 319 _opaque_connection res = *this;
334 { 320 res.pdest = newtarget;
335 FromT from; 321 return res;
336 ToT to; 322 }
337 }; 323
338 324 // Just calls the stored "emitter" function pointer stored at construction
339 emit_t pemit; 325 // time.
340 has_slots_interface* pdest; 326 template <typename... Args>
341 // Pointers to member functions may be up to 16 bytes for virtua l classes, 327 void emit(Args... args) const {
342 // so make sure we have enough space to store it. 328 typedef void (*em_t)(const _opaque_connection*, Args...);
343 unsigned char pmethod[16]; 329 union_caster<emit_t, em_t> caster;
344 330 caster.from = pemit;
345 public: 331 (caster.to)(this, args...);
346 template< typename DestT, typename ... Args > 332 }
347 _opaque_connection(DestT* pd, void (DestT::*pm)(Args...)) : pdes t(pd) 333
348 { 334 private:
349 typedef void (DestT::*pm_t)(Args...); 335 template <typename DestT, typename... Args>
350 static_assert(sizeof(pm_t) <= sizeof(pmethod), "Size of slot function pointer too large."); 336 static void emitter(const _opaque_connection* self, Args... args) {
351 337 typedef void (DestT::*pm_t)(Args...);
352 std::memcpy(pmethod, &pm, sizeof(pm_t)); 338 pm_t pm;
353 339 std::memcpy(&pm, self->pmethod, sizeof(pm_t));
354 typedef void (*em_t)(const _opaque_connection* self, Arg s...); 340 (static_cast<DestT*>(self->pdest)->*(pm))(args...);
355 union_caster< em_t, emit_t > caster2; 341 }
356 caster2.from = &_opaque_connection::emitter< DestT, Args ... >; 342 };
357 pemit = caster2.to; 343
358 } 344 template <class mt_policy>
359 345 class _signal_base : public _signal_base_interface, public mt_policy {
360 has_slots_interface* getdest() const { return pdest; } 346 protected:
361 347 typedef std::list<_opaque_connection> connections_list;
362 _opaque_connection duplicate(has_slots_interface* newtarget) con st 348
363 { 349 _signal_base()
364 _opaque_connection res = *this; 350 : _signal_base_interface(&_signal_base::do_slot_disconnect,
365 res.pdest = newtarget; 351 &_signal_base::do_slot_duplicate),
366 return res; 352 m_current_iterator(m_connected_slots.end()) {}
367 } 353
368 354 ~_signal_base() { disconnect_all(); }
369 // Just calls the stored "emitter" function pointer stored at co nstruction 355
370 // time. 356 private:
371 template< typename ... Args > 357 _signal_base& operator=(_signal_base const& that);
372 void emit(Args... args) const 358
373 { 359 public:
374 typedef void (*em_t)(const _opaque_connection*, Args...) ; 360 _signal_base(const _signal_base& o)
375 union_caster< emit_t, em_t > caster; 361 : _signal_base_interface(&_signal_base::do_slot_disconnect,
376 caster.from = pemit; 362 &_signal_base::do_slot_duplicate),
377 (caster.to)(this, args...); 363 m_current_iterator(m_connected_slots.end()) {
378 } 364 lock_block<mt_policy> lock(this);
379 365 for (const auto& connection : o.m_connected_slots) {
380 private: 366 connection.getdest()->signal_connect(this);
381 template< typename DestT, typename ... Args > 367 m_connected_slots.push_back(connection);
382 static void emitter(const _opaque_connection* self, Args... args ) 368 }
383 { 369 }
384 typedef void (DestT::*pm_t)(Args...); 370
385 pm_t pm; 371 bool is_empty() {
386 std::memcpy(&pm, self->pmethod, sizeof(pm_t)); 372 lock_block<mt_policy> lock(this);
387 (static_cast< DestT* >(self->pdest)->*(pm))(args...); 373 return m_connected_slots.empty();
388 } 374 }
389 }; 375
390 376 void disconnect_all() {
391 template<class mt_policy> 377 lock_block<mt_policy> lock(this);
392 class _signal_base : public _signal_base_interface, public mt_policy 378
393 { 379 while (!m_connected_slots.empty()) {
394 protected: 380 has_slots_interface* pdest = m_connected_slots.front().getdest();
395 typedef std::list< _opaque_connection > connections_list; 381 m_connected_slots.pop_front();
396 382 pdest->signal_disconnect(static_cast<_signal_base_interface*>(this));
397 _signal_base() : _signal_base_interface(&_signal_base::do_slot_d isconnect, &_signal_base::do_slot_duplicate), 383 }
398 m_current_iterator(m_connected_slots.end()) 384 // If disconnect_all is called while the signal is firing, advance the
399 { 385 // current slot iterator to the end to avoid an invalidated iterator from
400 } 386 // being dereferenced.
401 387 m_current_iterator = m_connected_slots.end();
402 ~_signal_base() 388 }
403 {
404 disconnect_all();
405 }
406
407 private:
408 _signal_base& operator= (_signal_base const& that);
409
410 public:
411 _signal_base(const _signal_base& o) : _signal_base_interface(&_s ignal_base::do_slot_disconnect, &_signal_base::do_slot_duplicate),
412 m_current_iterator(m_connected_slots.end()) {
413 lock_block<mt_policy> lock(this);
414 for (const auto& connection : o.m_connected_slots)
415 {
416 connection.getdest()->signal_connect(this);
417 m_connected_slots.push_back(connection);
418 }
419 }
420
421 bool is_empty()
422 {
423 lock_block<mt_policy> lock(this);
424 return m_connected_slots.empty();
425 }
426
427 void disconnect_all()
428 {
429 lock_block<mt_policy> lock(this);
430
431 while(!m_connected_slots.empty())
432 {
433 has_slots_interface* pdest = m_connected_slots.f ront().getdest();
434 m_connected_slots.pop_front();
435 pdest->signal_disconnect(static_cast< _signal_ba se_interface* >(this));
436 }
437 // If disconnect_all is called while the signal is firing, advance the
438 // current slot iterator to the end to avoid an invalidated iterator from
439 // being dereferenced.
440 m_current_iterator = m_connected_slots.end();
441 }
442 389
443 #if !defined(NDEBUG) 390 #if !defined(NDEBUG)
444 » » bool connected(has_slots_interface* pclass) 391 bool connected(has_slots_interface* pclass) {
445 » » { 392 lock_block<mt_policy> lock(this);
446 » » » lock_block<mt_policy> lock(this); 393 connections_list::const_iterator it = m_connected_slots.begin();
447 » » » connections_list::const_iterator it = m_connected_slots. begin(); 394 connections_list::const_iterator itEnd = m_connected_slots.end();
448 » » » connections_list::const_iterator itEnd = m_connected_slo ts.end(); 395 while (it != itEnd) {
449 » » » while(it != itEnd) 396 if (it->getdest() == pclass)
450 » » » { 397 return true;
451 » » » » if (it->getdest() == pclass) 398 ++it;
452 » » » » » return true; 399 }
453 » » » » ++it; 400 return false;
454 » » » } 401 }
455 » » » return false;
456 » » }
457 #endif 402 #endif
458 403
459 » » void disconnect(has_slots_interface* pclass) 404 void disconnect(has_slots_interface* pclass) {
460 » » { 405 lock_block<mt_policy> lock(this);
461 » » » lock_block<mt_policy> lock(this); 406 connections_list::iterator it = m_connected_slots.begin();
462 » » » connections_list::iterator it = m_connected_slots.begin( ); 407 connections_list::iterator itEnd = m_connected_slots.end();
463 » » » connections_list::iterator itEnd = m_connected_slots.end (); 408
464 409 while (it != itEnd) {
465 » » » while(it != itEnd) 410 if (it->getdest() == pclass) {
466 » » » { 411 // If we're currently using this iterator because the signal is firing,
467 » » » » if(it->getdest() == pclass) 412 // advance it to avoid it being invalidated.
468 » » » » { 413 if (m_current_iterator == it) {
469 // If we're currently using this iterator because the signal is 414 m_current_iterator = m_connected_slots.erase(it);
470 // firing, advance it to avoid it being invalidated. 415 } else {
471 if (m_current_iterator == it) { 416 m_connected_slots.erase(it);
472 m_current_iterator = m_connected_slots.erase(it);
473 } else {
474 m_connected_slots.erase(it);
475 }
476 » » » » » pclass->signal_disconnect(static_cast< _ signal_base_interface* >(this));
477 » » » » » return;
478 » » » » }
479
480 » » » » ++it;
481 » » » }
482 » » }
483
484 » private:
485 » » static void do_slot_disconnect(_signal_base_interface* p, has_sl ots_interface* pslot)
486 » » {
487 » » » _signal_base* const self = static_cast< _signal_base* >( p);
488 » » » lock_block<mt_policy> lock(self);
489 » » » connections_list::iterator it = self->m_connected_slots. begin();
490 » » » connections_list::iterator itEnd = self->m_connected_slo ts.end();
491
492 » » » while(it != itEnd)
493 » » » {
494 » » » » connections_list::iterator itNext = it;
495 » » » » ++itNext;
496
497 » » » » if(it->getdest() == pslot)
498 » » » » {
499 // If we're currently using this iterator because the signal is
500 // firing, advance it to avoid it being invalidated.
501 if (self->m_current_iterator == it) {
502 self->m_current_iterator = self->m_connected_slots.erase(it);
503 } else {
504 self->m_connected_slots.erase(it);
505 }
506 } 417 }
507 418 pclass->signal_disconnect(static_cast<_signal_base_interface*>(this));
508 » » » » it = itNext; 419 return;
509 » » » }
510 » » }
511
512 » » static void do_slot_duplicate(_signal_base_interface* p, const h as_slots_interface* oldtarget, has_slots_interface* newtarget)
513 » » {
514 » » » _signal_base* const self = static_cast< _signal_base* >( p);
515 » » » lock_block<mt_policy> lock(self);
516 » » » connections_list::iterator it = self->m_connected_slots. begin();
517 » » » connections_list::iterator itEnd = self->m_connected_slo ts.end();
518
519 » » » while(it != itEnd)
520 » » » {
521 » » » » if(it->getdest() == oldtarget)
522 » » » » {
523 » » » » » self->m_connected_slots.push_back(it->du plicate(newtarget));
524 » » » » }
525
526 » » » » ++it;
527 » » » }
528 » » }
529
530 » protected:
531 » » connections_list m_connected_slots;
532
533 // Used to handle a slot being disconnected while a signal is
534 // firing (iterating m_connected_slots).
535 connections_list::iterator m_current_iterator;
536 };
537
538 » template<class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
539 » class has_slots : public has_slots_interface, public mt_policy
540 » {
541 » private:
542 » » typedef std::set< _signal_base_interface* > sender_set;
543 » » typedef sender_set::const_iterator const_iterator;
544
545 » public:
546 » » has_slots() : has_slots_interface(&has_slots::do_signal_connect, &has_slots::do_signal_disconnect, &has_slots::do_disconnect_all)
547 » » {
548 » » }
549
550 » » has_slots(has_slots const& o) : has_slots_interface(&has_slots:: do_signal_connect, &has_slots::do_signal_disconnect, &has_slots::do_disconnect_a ll)
551 {
552 » » » lock_block<mt_policy> lock(this);
553 for (auto* sender : o.m_senders) {
554 sender->slot_duplicate(&o, this);
555 m_senders.insert(sender);
556 } 420 }
557 } 421 ++it;
558 422 }
559 ~has_slots() 423 }
560 { 424
561 this->disconnect_all(); 425 private:
562 } 426 static void do_slot_disconnect(_signal_base_interface* p,
563 427 has_slots_interface* pslot) {
564 private: 428 _signal_base* const self = static_cast<_signal_base*>(p);
565 has_slots& operator= (has_slots const&); 429 lock_block<mt_policy> lock(self);
566 430 connections_list::iterator it = self->m_connected_slots.begin();
567 static void do_signal_connect(has_slots_interface* p, _signal_ba se_interface* sender) 431 connections_list::iterator itEnd = self->m_connected_slots.end();
568 { 432
569 has_slots* const self = static_cast< has_slots* >(p); 433 while (it != itEnd) {
570 lock_block<mt_policy> lock(self); 434 connections_list::iterator itNext = it;
571 self->m_senders.insert(sender); 435 ++itNext;
572 } 436
573 437 if (it->getdest() == pslot) {
574 static void do_signal_disconnect(has_slots_interface* p, _signal _base_interface* sender) 438 // If we're currently using this iterator because the signal is firing,
575 { 439 // advance it to avoid it being invalidated.
576 has_slots* const self = static_cast< has_slots* >(p); 440 if (self->m_current_iterator == it) {
577 lock_block<mt_policy> lock(self); 441 self->m_current_iterator = self->m_connected_slots.erase(it);
578 self->m_senders.erase(sender); 442 } else {
579 } 443 self->m_connected_slots.erase(it);
580 444 }
581 static void do_disconnect_all(has_slots_interface* p) 445 }
582 { 446
583 has_slots* const self = static_cast< has_slots* >(p); 447 it = itNext;
584 lock_block<mt_policy> lock(self); 448 }
585 while (!self->m_senders.empty()) 449 }
586 { 450
587 std::set< _signal_base_interface* > senders; 451 static void do_slot_duplicate(_signal_base_interface* p,
588 senders.swap(self->m_senders); 452 const has_slots_interface* oldtarget,
589 const_iterator it = senders.begin(); 453 has_slots_interface* newtarget) {
590 const_iterator itEnd = senders.end(); 454 _signal_base* const self = static_cast<_signal_base*>(p);
591 455 lock_block<mt_policy> lock(self);
592 while(it != itEnd) 456 connections_list::iterator it = self->m_connected_slots.begin();
593 { 457 connections_list::iterator itEnd = self->m_connected_slots.end();
594 _signal_base_interface* s = *it; 458
595 ++it; 459 while (it != itEnd) {
596 s->slot_disconnect(p); 460 if (it->getdest() == oldtarget) {
597 } 461 self->m_connected_slots.push_back(it->duplicate(newtarget));
598 } 462 }
599 } 463
600 464 ++it;
601 private: 465 }
602 sender_set m_senders; 466 }
603 }; 467
604 468 protected:
605 template<class mt_policy, typename ... Args> 469 connections_list m_connected_slots;
606 class signal_with_thread_policy : public _signal_base<mt_policy> 470
607 { 471 // Used to handle a slot being disconnected while a signal is
608 private: 472 // firing (iterating m_connected_slots).
609 typedef _signal_base<mt_policy> base; 473 connections_list::iterator m_current_iterator;
610 474 bool m_erase_current_iterator = false;
611 protected: 475 };
612 typedef typename base::connections_list connections_list; 476
613 477 template <class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
614 public: 478 class has_slots : public has_slots_interface, public mt_policy {
615 signal_with_thread_policy() 479 private:
616 { 480 typedef std::set<_signal_base_interface*> sender_set;
617 } 481 typedef sender_set::const_iterator const_iterator;
618 482
619 template<class desttype> 483 public:
620 void connect(desttype* pclass, void (desttype::*pmemfun)(Args... )) 484 has_slots()
621 { 485 : has_slots_interface(&has_slots::do_signal_connect,
622 lock_block<mt_policy> lock(this); 486 &has_slots::do_signal_disconnect,
623 this->m_connected_slots.push_back(_opaque_connection(pcl ass, pmemfun)); 487 &has_slots::do_disconnect_all) {}
624 pclass->signal_connect(static_cast< _signal_base_interfa ce* >(this)); 488
625 } 489 has_slots(has_slots const& o)
626 490 : has_slots_interface(&has_slots::do_signal_connect,
627 void emit(Args... args) 491 &has_slots::do_signal_disconnect,
628 { 492 &has_slots::do_disconnect_all) {
629 lock_block<mt_policy> lock(this); 493 lock_block<mt_policy> lock(this);
630 this->m_current_iterator = 494 for (auto* sender : o.m_senders) {
631 this->m_connected_slots.begin(); 495 sender->slot_duplicate(&o, this);
632 while (this->m_current_iterator != 496 m_senders.insert(sender);
633 this->m_connected_slots.end()) { 497 }
634 _opaque_connection const& conn = 498 }
635 *this->m_current_iterator; 499
636 ++(this->m_current_iterator); 500 ~has_slots() { this->disconnect_all(); }
637 conn.emit<Args...>(args...); 501
638 } 502 private:
639 } 503 has_slots& operator=(has_slots const&);
640 504
641 void operator()(Args... args) 505 static void do_signal_connect(has_slots_interface* p,
642 { 506 _signal_base_interface* sender) {
643 emit(args...); 507 has_slots* const self = static_cast<has_slots*>(p);
644 } 508 lock_block<mt_policy> lock(self);
645 }; 509 self->m_senders.insert(sender);
646 510 }
647 // Alias with default thread policy. Needed because both default argumen ts 511
648 // and variadic template arguments must go at the end of the list, so we 512 static void do_signal_disconnect(has_slots_interface* p,
649 // can't have both at once. 513 _signal_base_interface* sender) {
650 template<typename ... Args> 514 has_slots* const self = static_cast<has_slots*>(p);
651 using signal = signal_with_thread_policy<SIGSLOT_DEFAULT_MT_POLICY, Args ...>; 515 lock_block<mt_policy> lock(self);
652 516 self->m_senders.erase(sender);
653 // The previous verion of sigslot didn't use variadic templates, so you would 517 }
654 // need to write "sigslot::signal2<Arg1, Arg2>", for example. 518
655 // Now you can just write "sigslot::signal<Arg1, Arg2>", but these alias es 519 static void do_disconnect_all(has_slots_interface* p) {
656 // exist for backwards compatibility. 520 has_slots* const self = static_cast<has_slots*>(p);
657 template<typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY> 521 lock_block<mt_policy> lock(self);
658 using signal0 = signal_with_thread_policy<mt_policy>; 522 while (!self->m_senders.empty()) {
659 523 std::set<_signal_base_interface*> senders;
660 template<typename A1, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY> 524 senders.swap(self->m_senders);
661 using signal1 = signal_with_thread_policy<mt_policy, A1>; 525 const_iterator it = senders.begin();
662 526 const_iterator itEnd = senders.end();
663 template<typename A1, typename A2, typename mt_policy = SIGSLOT_DEFAULT_ MT_POLICY> 527
664 using signal2 = signal_with_thread_policy<mt_policy, A1, A2>; 528 while (it != itEnd) {
665 529 _signal_base_interface* s = *it;
666 template<typename A1, typename A2, typename A3, typename mt_policy = SIG SLOT_DEFAULT_MT_POLICY> 530 ++it;
667 using signal3 = signal_with_thread_policy<mt_policy, A1, A2, A3>; 531 s->slot_disconnect(p);
668 532 }
669 template<typename A1, typename A2, typename A3, typename A4, typename mt _policy = SIGSLOT_DEFAULT_MT_POLICY> 533 }
670 using signal4 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4>; 534 }
671 535
672 template<typename A1, typename A2, typename A3, typename A4, typename A5 , typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY> 536 private:
673 using signal5 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5> ; 537 sender_set m_senders;
674 538 };
675 template<typename A1, typename A2, typename A3, typename A4, typename A5 , typename A6, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY> 539
676 using signal6 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6>; 540 template <class mt_policy, typename... Args>
677 541 class signal_with_thread_policy : public _signal_base<mt_policy> {
678 template<typename A1, typename A2, typename A3, typename A4, typename A5 , typename A6, typename A7, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY> 542 private:
679 using signal7 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7>; 543 typedef _signal_base<mt_policy> base;
680 544
681 template<typename A1, typename A2, typename A3, typename A4, typename A5 , typename A6, typename A7, typename A8, typename mt_policy = SIGSLOT_DEFAULT_MT _POLICY> 545 protected:
682 using signal8 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7, A8>; 546 typedef typename base::connections_list connections_list;
683 547
684 } // namespace sigslot 548 public:
685 549 signal_with_thread_policy() {}
686 #endif // WEBRTC_BASE_SIGSLOT_H__ 550
551 template <class desttype>
552 void connect(desttype* pclass, void (desttype::*pmemfun)(Args...)) {
553 lock_block<mt_policy> lock(this);
554 this->m_connected_slots.push_back(_opaque_connection(pclass, pmemfun));
555 pclass->signal_connect(static_cast<_signal_base_interface*>(this));
556 }
557
558 void emit(Args... args) {
559 lock_block<mt_policy> lock(this);
560 this->m_current_iterator = this->m_connected_slots.begin();
561 while (this->m_current_iterator != this->m_connected_slots.end()) {
562 _opaque_connection const& conn = *this->m_current_iterator;
563 ++(this->m_current_iterator);
564 conn.emit<Args...>(args...);
565 }
566 }
567
568 void operator()(Args... args) { emit(args...); }
569 };
570
571 // Alias with default thread policy. Needed because both default arguments
572 // and variadic template arguments must go at the end of the list, so we
573 // can't have both at once.
574 template <typename... Args>
575 using signal = signal_with_thread_policy<SIGSLOT_DEFAULT_MT_POLICY, Args...>;
576
577 // The previous verion of sigslot didn't use variadic templates, so you would
578 // need to write "sigslot::signal2<Arg1, Arg2>", for example.
579 // Now you can just write "sigslot::signal<Arg1, Arg2>", but these aliases
580 // exist for backwards compatibility.
581 template <typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
582 using signal0 = signal_with_thread_policy<mt_policy>;
583
584 template <typename A1, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
585 using signal1 = signal_with_thread_policy<mt_policy, A1>;
586
587 template <typename A1,
588 typename A2,
589 typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
590 using signal2 = signal_with_thread_policy<mt_policy, A1, A2>;
591
592 template <typename A1,
593 typename A2,
594 typename A3,
595 typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
596 using signal3 = signal_with_thread_policy<mt_policy, A1, A2, A3>;
597
598 template <typename A1,
599 typename A2,
600 typename A3,
601 typename A4,
602 typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
603 using signal4 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4>;
604
605 template <typename A1,
606 typename A2,
607 typename A3,
608 typename A4,
609 typename A5,
610 typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
611 using signal5 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5>;
612
613 template <typename A1,
614 typename A2,
615 typename A3,
616 typename A4,
617 typename A5,
618 typename A6,
619 typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
620 using signal6 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6>;
621
622 template <typename A1,
623 typename A2,
624 typename A3,
625 typename A4,
626 typename A5,
627 typename A6,
628 typename A7,
629 typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
630 using signal7 =
631 signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7>;
632
633 template <typename A1,
634 typename A2,
635 typename A3,
636 typename A4,
637 typename A5,
638 typename A6,
639 typename A7,
640 typename A8,
641 typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
642 using signal8 =
643 signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7, A8>;
644
645 } // namespace sigslot
646
647 #endif // WEBRTC_BASE_SIGSLOT_H__
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698