c++-gtk-utils
emitter.h
Go to the documentation of this file.
1 /* Copyright (C) 2009 to 2014 Chris Vine
2 
3 The library comprised in this file or of which this file is part is
4 distributed by Chris Vine under the GNU Lesser General Public
5 License as follows:
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Lesser General Public License
9  as published by the Free Software Foundation; either version 2.1 of
10  the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License, version 2.1, for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License, version 2.1, along with this library (see the file LGPL.TXT
19  which came with this source code package in the c++-gtk-utils
20  sub-directory); if not, write to the Free Software Foundation, Inc.,
21  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 
23 However, it is not intended that the object code of a program whose
24 source code instantiates a template from this file or uses macros or
25 inline functions (of any length) should by reason only of that
26 instantiation or use be subject to the restrictions of use in the GNU
27 Lesser General Public License. With that in mind, the words "and
28 macros, inline functions and instantiations of templates (of any
29 length)" shall be treated as substituted for the words "and small
30 macros and small inline functions (ten lines or less in length)" in
31 the fourth paragraph of section 5 of that licence. This does not
32 affect any other reason why object code may be subject to the
33 restrictions in that licence (nor for the avoidance of doubt does it
34 affect the application of section 2 of that licence to modifications
35 of the source code in this file).
36 
37 */
38 
39 #ifndef CGU_EMITTER_H
40 #define CGU_EMITTER_H
41 
42 /**
43  * @file emitter.h
44  * @brief This file provides a thread-safe signal/slot mechanism, with
45  * automatic disconnection.
46  *
47  * An EmitterArg object is a list of Callback::FunctorArg objects.
48  * Callback::FunctorArg objects may be "connected" to the EmitterArg
49  * object, and all functors so connected will be executed when the
50  * operator()() or emit() member functions of the EmitterArg object
51  * concerned is called. They will be called in the order in which
52  * they were connected. Emitter is a typedef for EmitterArg<>. The
53  * generalised EmitterArg<T...> type contains
54  * Callback::FunctorArg<T...> objects (types T... being the unbound
55  * arguments of a Callback::CallbackArg<T...> callback - see
56  * Cgu::Callback for further details, and "Usage" below for examples.)
57  * The Emitter type holds Callback::Functor (namely
58  * Callback::FunctorArg<>) objects.
59  *
60  * The main advantage of an emitter object as opposed to storing a
61  * functor object directly, apart from the fact that more than one
62  * functor can be dispatched by a single call to EmitterArg::emit() or
63  * EmitterArg::operator()(), is that it provides for automatic
64  * disconnection of a functor if the object whose member function it
65  * represents has ceased to exist.
66  *
67  * Where automatic disconnection is wanted, the object whose method is
68  * to be encapsulated by a functor must have a Releaser object as a
69  * public member. The Releaser object should be passed as the second
70  * argument of EmitterArg::connect(). As well as a Releaser object
71  * informing an emitter object when it has ceased to exist, an emitter
72  * object will do the same to the Releaser object if the emitter
73  * object happens to be destroyed before an object whose members it
74  * references (and therefore before the Releaser object). Automatic
75  * disconnection is mainly useful for non-static member functions, but
76  * it can be employed for static member functions or non-member
77  * functions if wanted (that will in effect bind the lifetime of the
78  * functor to that of the object to whose Releaser the functor has
79  * been attached.)
80  *
81  * It is safe for a connected function (i) to delete the EmitterArg
82  * object to which it is connected, even if there are other functors
83  * still to execute in the same emission (which will execute normally
84  * provided they do not try to call any of the emitter's functions),
85  * (ii) to call 'delete this' nothwithstanding that the connected
86  * function is protected by a Releaser object (assuming all the other
87  * restraints on calling 'delete this' are met), provided that no
88  * other access would be made to the deleted object in a function call
89  * connected to the same emitter which is due to execute subsequently
90  * in the same emission, and (iii) to disconnect itself from the
91  * EmitterArg object. This design approach has a trade-off: if a
92  * connected function tries to block, unblock or disconnect another
93  * function connected to the same EmitterArg object which is due to
94  * execute subsequently in the same emission (or to block, unblock or
95  * disconnect itself when it is due to execute again subsequently in
96  * the same emission), the attempted block, unblock or disconnection
97  * will not have any effect on that emission (it will only have effect
98  * on a subsequent emission). In addition, a connected function may
99  * not destroy an object whose non-static method is connected to the
100  * same emitter and which would execute subsequently in the same
101  * emission, even if that object is protected by a Releaser object
102  * (the non-static method will unsuccessfully attempt to execute
103  * notwithstanding the destruction of the object it would be operating
104  * on).
105  *
106  * The SafeEmitterArg classes are the same as their EmitterArg
107  * counterparts except that they contain Callback::SafeFunctorArg
108  * objects, and their emit(), operator()(), connect(), disconnect(),
109  * block(), unblock() and destructor methods are protected by a mutex
110  * so that different threads can call these methods on the same
111  * emitter object, or create and delete the object.
112  *
113  * Note that the mutexes are released when the operator()()/emit()
114  * methods of the relevent Callback::SafeFunctorArg objects are
115  * called, as SafeEmitterArg objects have no idea what the referenced
116  * callbacks will do so if they were not released deadlocks could
117  * arise from recursive or out-of-order locking of the SafeEmitterArg
118  * mutex. It is therefore for users to provide additional
119  * synchronisation if the functions encapsulated by the relevant
120  * functors themselves need additional protection. Note also the
121  * subsidiary thread-safety points mentioned below.
122  *
123  * The Releaser class is intrinsically thread safe (the overhead of
124  * locking is so low that it is pointless having a separate
125  * unprotected class). This means that if a program is
126  * multi-threaded, you can use the plain EmitterArg classes provided
127  * that only the thread which creates a particular EmitterArg object
128  * calls connect(), block(), unblock((), emit() or operator()() on it,
129  * or deletes it, or calls disconnect() on it (either directly or
130  * through a Releaser object being destroyed). Where more than one
131  * thread might do that in relation to any one emitter object, use
132  * SafeEmitterArg.
133  *
134  * Alternatives
135  * ------------
136  *
137  * These classes are intended as a lightweight thread-safe signal/slot
138  * mechanism for GUI programming. For more demanding usage libsigc++
139  * is a good choice, except that it is not thread-safe. An
140  * alternative to libsigc++ is the boost::signal2 module, which is
141  * thread-safe.
142  *
143  * Subsidiary thread-safety points
144  * -------------------------------
145  *
146  * As mentioned, the SafeEmitterArg classes are thread safe, and their
147  * methods can be called in different threads without ill effect.
148  * However, there are some things that cannot be done. Users should
149  * observe two points.
150  *
151  * First, it has been mentioned that if a connected function blocks,
152  * unblocks or disconnects another function connected to the same
153  * emitter object and due to execute subsequently in the same
154  * emission, the blocking, unblocking or disconnection will not have
155  * effect in that emission, and that a connected function may not
156  * delete an object whose non-static method is due to execute
157  * subsequently in the same emission. The same outcome would result
158  * if another thread tries to do any of these things while an emission
159  * is under way. Another thread should therefore leave alone objects
160  * connected to a SafeEmitterArg object from the time of operator()()
161  * or emit() beginning to the time of it ending, and not try to
162  * interfere.
163  *
164  * Secondly, when a Releaser object is passed as the second argument
165  * to the connect() method of a SafeEmitterArg object, the Releaser
166  * object must remain in existence until the connect() method returns
167  * or the emitter may be left in an inconsistent state.
168  *
169  * @anchor AssignmentAnchor
170  * Assignment
171  * ----------
172  *
173  * EmitterArg and SafeEmitterArg objects cannot be copied. Releaser
174  * objects can be (we do not want to make a class uncopiable just
175  * because it has the safety feature of having a Releaser object as a
176  * member).
177  *
178  * So how should assignment of a Releaser object and of a class which
179  * has a Releaser as a member be handled? An object which has a
180  * Releaser as a member and which is being assigned to (the assignee)
181  * could keep all its existing pre-assignment emitter connections - so
182  * far as the Releaser object is concerned, it will have to do so
183  * where the connections are not protected by the Releaser object, and
184  * we could do the same in relation to protected connections, in which
185  * case we would make operator=() of Releaser do nothing: that is,
186  * just return - a default assignment would always be wrong as it
187  * would take the assignor's Releaser state but inherit none of its
188  * connections, which the assignee cannot inherit as they depend on a
189  * remote emitter object or objects.
190  *
191  * However, the state of the assignee after assignment may not be such
192  * as to permit the inheriting of all the assignor's state except its
193  * connections. Accordingly, the default strategy adopted here is for
194  * the Releaser object to become a blank sheet on assignment. After
195  * assignment, an assignee which has a Releaser object as a member
196  * will no longer have any of the emitter connections which were,
197  * prior to assignment, protected by the Releaser object. If in a
198  * particular case the user does not want this behaviour, she should
199  * provide an assignment operator in the class which has Releaser as a
200  * member and leave Releaser alone in the assignment operator.
201  *
202  * Usage
203  * -----
204  *
205  * These are examples:
206  *
207  * @code
208  * using namespace Cgu;
209  *
210  * Emitter e1;
211  * e1.connect(Callback::lambda<>([] () {std::cout << "Hello world\n";}));
212  * e1();
213  *
214  * SafeEmitter se1;
215  * se1.connect(Callback::lambda<>([] () {std::cout << "Hello world\n";}));
216  * se1();
217  *
218  * int res;
219  * EmitterArg<int, int&> e2;
220  * e2.connect(Callback::lambda<int, int&>([] (int i, int& j) {j = 10 * i;}));
221  * e2(2, res);
222  * std::cout << "10 times 2 is " << res << '\n';
223  *
224  * SafeEmitterArg<int, int&> se2;
225  * se2.connect(Callback::lambda<int, int&>([] (int i, int& j) {j = 10 * i;}));
226  * se2(2, res);
227  * std::cout << "10 times 2 is " << res << '\n';
228  * @endcode
229  *
230  * EmitterArg classes do not provide for a return value. If a
231  * result is wanted, users should pass an unbound argument by
232  * reference or pointer (or pointer to pointer).
233  *
234  * Exception safety
235  * ----------------
236  *
237  * Apart from the emit()/operator()() and connect() methods, nothing
238  * done to an EmitterArg/SafeEmitterArg object should cause an
239  * exception to be thrown. This is because other methods only iterate
240  * through a std::list object using std::for_each(), std::find() or by
241  * hand, and the only things done by std::for_each() or after a
242  * std::find() or iteration is to remove a functor from the list
243  * (copying a functor and comparing functors never throw, nor does
244  * destroying a functor provided the destructors of any bound argument
245  * type do not throw). Thus, an EmitterArg/SafeEmitterArg and
246  * Releaser object should never get into an inconsistent state.
247  *
248  * The connect() method could throw a std::bad_alloc exception, either
249  * on creating new functors or on pushing the functors onto the list.
250  * However, were it to do so, the method has strong exception safety
251  * (assuming merely iterating over a list does not throw, as it should
252  * not).
253  *
254  * The emit()/operator()() methods could throw std::bad_alloc, and so
255  * far as that is concerned emission of all the connected functions
256  * will either all succeed or all fail. In addition, the connected
257  * functions referenced by the functors held by the emitter might
258  * throw when executed. emit()/operator()() do not attempt to catch
259  * these exceptions as there is nothing they could do with them. This
260  * means that although a throwing connected function will not leave
261  * the EmitterArg/SafeEmitterArg object in an inconsistent state, any
262  * other connected functions due to execute subsequently on that same
263  * emission will not execute. If that is important in any particular
264  * case, the user must incorporate logic in the connected functions to
265  * cater for an exception causing only part execution, or must connect
266  * only one function to any one signal and "chain" emissions by hand
267  * so as to do the right thing.
268  */
269 
270 /*
271  Mutex locking heirarchy:
272 
273  Some out-of-order locking must take place because of the
274  relationship between the Releaser and SafeEmitterArg<> classes. The
275  mutex of Releaser is given the higher priority. This means that a
276  plain EmitterArg<> object will not take any hit from the fact that
277  Releaser is also useable with SafeEmitterArg<> objects.
278 
279  One consequence is that to avoid deadlocks, it is the
280  SafeEmitterArg<> functions which must yield when a deadlock would
281  otherwise arise. Yielding could occur in
282  SafeEmitterArg<>::~SafeEmitterArg() and
283  SafeEmitterArg<>::disconnect().
284 */
285 
286 #ifdef CGU_USE_SCHED_YIELD
287 #include <sched.h>
288 #else
289 #include <unistd.h>
290 #endif
291 
292 #include <list>
293 #include <unordered_set>
294 #include <algorithm>
295 #include <functional>
296 #include <utility> // for std::move
297 
298 #include <c++-gtk-utils/callback.h>
299 #include <c++-gtk-utils/mutex.h>
301 
302 namespace Cgu {
303 
304 /* The four basic emitter types */
305 
306 template <class... FreeArgs> class EmitterArg;
307 template <class... FreeArgs> class SafeEmitterArg;
308 typedef EmitterArg<> Emitter;
310 
311 /**
312  * @class Releaser emitter.h c++-gtk-utils/emitter.h
313  * @brief A class used for tracking EmitterArg and SafeEmitterArg
314  * connections.
315  * @sa EmitterArg SafeEmitterArg
316  * @sa emitter.h
317  * @sa Callback namespace
318  *
319  * This class provides tracking of EmitterArg and SafeEmitterArg
320  * connections. It should be a public member of any target class
321  * which wants functors representing any of its methods to be
322  * disconnected automatically from an EmitterArg or SafeEmitterArg
323  * object when the target class object is destroyed, and is passed as
324  * one of the arguments to the connect() method of EmitterArg or
325  * SafeEmitterArg.
326  *
327  * All its methods are thread-safe.
328  *
329  * For further background, read this: emitter.h
330  */
331 
332 class Releaser {
333 
334  // from version 2.0.0-rc3 we use std::unordered_set rather than
335  // std::list in Releaser. We can't do that for
336  // EmitterArg/SafeEmitterArg objects, as they need to execute
337  // connected functors in the order in which they were connected.
338  std::unordered_set<Callback::SafeFunctor> disconnect_set;
339  Thread::Mutex mutex;
340 
341  // only an EmitterArg or SafeEmitterArg object can access add(), remove and try_remove()
342  void add(const Callback::SafeFunctor&);
343  void remove(const Callback::SafeFunctor&);
344  void try_remove(const Callback::SafeFunctor&, int*);
345 public:
346  template <class... T> friend class EmitterArg;
347  template <class... T> friend class SafeEmitterArg;
348 
349  // operator=() and the copy constructor should copy nothing from the
350  // assignor, because disconnect_set should be empty in the
351  // assignee, as any class containing us does not acquire as assignee
352  // any emitter functors representing any of its methods
353 
354 /**
355  * See notes on @ref AssignmentAnchor "assignment" to see how this
356  * operates. This does not throw provided that the destructors of any
357  * bound arguments of a functor managed by this Releaser object prior
358  * to assignment do not throw (as they should not do), and assuming
359  * that merely iterating through a list does not throw (as it would
360  * not on any sane implementation).
361  * @param r The assignee.
362  */
363  Releaser& operator=(const Releaser& r);
364 
365 /**
366  * This does not copy anything from the Releaser object passed as an
367  * argument - see the notes on @ref AssignmentAnchor "assignment" for
368  * an explanation of why. This does not throw.
369  * @param r A Releaser object.
370  * @exception std::bad_alloc This constructor might throw
371  * std::bad_alloc if memory is exhausted and the system throws in that
372  * case.
373  * @exception Thread::MutexError This constructor might throw
374  * Thread::MutexError if initialisation of the contained mutex fails.
375  * (It is often not worth checking for this, as it means either memory
376  * is exhausted or pthread has run out of other resources to create
377  * new mutexes.)
378  */
379  Releaser(const Releaser& r) {}
380 
381 /**
382  * @exception std::bad_alloc The default constructor might throw
383  * std::bad_alloc if memory is exhausted and the system throws in that
384  * case.
385  * @exception Thread::MutexError The default constructor might throw
386  * Thread::MutexError if initialisation of the contained mutex fails.
387  * (It is often not worth checking for this, as it means either memory
388  * is exhausted or pthread has run out of other resources to create
389  * new mutexes.)
390  */
391  Releaser() = default;
392 
393 /**
394  * The destructor does not throw provided that the destructors of any
395  * bound arguments of a functor managed by this Releaser object do not
396  * throw (as they should not do), and assuming that merely iterating
397  * through an unordered_set does not throw (as it would not on any
398  * sane implementation).
399  */
400  ~Releaser();
401 
402 /* Only has effect if --with-glib-memory-slices-compat or
403  * --with-glib-memory-slices-no-compat option picked */
405 };
406 
407 /* the emitter classes */
408 
409 /**
410  * @class EmitterArg emitter.h c++-gtk-utils/emitter.h
411  * @brief A class to execute callbacks connected to it, with provision
412  * for automatic disconnection.
413  * @sa SafeEmitterArg Releaser
414  * @sa emitter.h
415  * @sa Callback namespace
416  *
417  * Callback::FunctorArg objects may be connected to Emitter classes,
418  * and will be executed when EmitterArg::emit() or
419  * EmitterArg::operator()() are called.
420  *
421  * One version of the connect() method takes a Releaser object as an
422  * argument. Such a Releaser object should be a public member of any
423  * target class which wants functors representing (or calling into)
424  * any of its methods to be disconnected automatically from the
425  * EmitterArg object when the target class object is destroyed.
426  *
427  * A connection may be explicitly disconnected by calling the
428  * disconnect() method, and may also be temporarily blocked and
429  * subsequently unblocked with the block() and unblock() methods.
430  *
431  * The template types are the types of the unbound arguments, if any.
432  * EmitterArg<> is typedef'ed to Emitter.
433  *
434  * @b Usage
435  *
436  * These are examples:
437  *
438  * @code
439  * using namespace Cgu;
440  *
441  * Emitter e1;
442  * e1.connect(Callback::lambda<>([] () {std::cout << "Hello world\n";}));
443  * e1();
444  *
445  * int res;
446  * EmitterArg<int, int&> e2;
447  * e2.connect(Callback::lambda<int, int&>([] (int i, int& j) {j = 10 * i;}));
448  * e2(2, res);
449  * std::cout << "10 times 2 is " << res << '\n';
450  * @endcode
451  *
452  * For further background, including about thread-safety and exception
453  * safety and other matters, read this: emitter.h, or for more
454  * information about bound and unbound arguments, read this:
455  * Cgu::Callback.
456  */
457 
458 template <class... FreeArgs>
459 class EmitterArg {
460 
461 #ifndef DOXYGEN_PARSING
462  // f1 is the functor we execute when we emit()
463  // f2 is the functor we execute in our destructor if we are destroyed
464  // before the remote object is
465  struct ListItem {
466  Callback::FunctorArg<FreeArgs...> f1;
468  bool blocked;
469  ListItem(Callback::FunctorArg<FreeArgs...> f1_, Callback::Functor f2_):
470  f1(f1_), f2(f2_), blocked(false) {}
471  };
472 #endif
473 
474  std::list<ListItem> emission_list;
475 
476  // only Releaser objects can access this
477  void tracking_disconnect(const Callback::FunctorArg<FreeArgs...>&);
478 
479 public:
480  friend class Releaser;
481 
482 /**
483  * This will execute the connected functors.
484  * @param args The unbound arguments to be passed to the referenced
485  * function or class method, if any.
486  * @exception std::bad_alloc The method might throw std::bad_alloc if
487  * memory is exhausted and the system throws in that case. In
488  * addition, it will throw if the functions or class methods
489  * referenced by the functors throw (or if the copy constructor of a
490  * free or bound argument throws and it is not a reference argument).
491  */
492  void operator()(typename Cgu::Param<FreeArgs>::ParamType... args) const {emit(args...);}
493 
494 /**
495  * This will execute the connected functors.
496  * @param args The unbound arguments to be passed to the referenced
497  * function or class method, if any.
498  * @exception std::bad_alloc The method might throw std::bad_alloc if
499  * memory is exhausted and the system throws in that case. In
500  * addition, it will throw if the functions or class methods
501  * referenced by the functors throw (or if the copy constructor of a
502  * free or bound argument throws and it is not a reference argument).
503  */
504  void emit(typename Cgu::Param<FreeArgs>::ParamType... args) const;
505 
506 /**
507  * This will execute the connected functors, but it also reports
508  * whether in fact there were any connected functors to execute. (It
509  * is not necessary to use this function just because it is not known
510  * whether a functor is connected - if the standard emit() function is
511  * called when no functor is connected, nothing will happen. The
512  * feature of this method is that it will report the outcome.)
513  * @param args The unbound arguments to be passed to the connected
514  * functions or class methods, if any.
515  * @return Returns false if there were no functors to execute, or true
516  * if functors have been executed.
517  * @exception std::bad_alloc The method might throw std::bad_alloc if
518  * memory is exhausted and the system throws in that case. In
519  * addition, it will throw if the functions or class methods
520  * referenced by the functors throw (or if the copy constructor of a
521  * free or bound argument throws and it is not a reference argument).
522  */
523  bool test_emit(typename Cgu::Param<FreeArgs>::ParamType... args) const;
524 
525 /**
526  * Connects a functor.
527  * @param f The functor to connect.
528  * @return The functor connected.
529  * @exception std::bad_alloc The method might throw std::bad_alloc if
530  * memory is exhausted and the system throws in that case.
531  */
533 
534 /**
535  * Connects a functor.
536  * @param f The functor to connect.
537  * @param r A Releaser object for automatic disconnection of the
538  * functor if the object whose method it represents is destroyed.
539  * @return The functor connected.
540  * @exception std::bad_alloc The method might throw std::bad_alloc if
541  * memory is exhausted and the system throws in that case.
542  */
544 
545 /**
546  * Disconnects a functor previously connected. This does not throw
547  * provided that the destructors of any bound arguments do not throw
548  * (as they should not do), and assuming that merely iterating through
549  * a list does not throw (as it would not on any sane implementation).
550  * @param f The functor to disconnect.
551  * @note If the same functor has been connected more than once to the
552  * same EmitterArg object, this call will disconnect all of them.
553  */
555 
556 /**
557  * Blocks a connected functor from executing when emit() or
558  * operator()() is called until unblock() is called. This method does
559  * not throw (assuming that merely iterating through a list does not
560  * throw, as it would not on any sane implementation).
561  * @param f The functor to block.
562  * @note If the same functor has been connected more than once to the
563  * same EmitterArg object, this call will block all of them.
564  */
566 
567 /**
568  * Unblocks a previously blocked functor. This method does not throw
569  * (assuming that merely iterating through a list does not throw, as
570  * it would not on any sane implementation).
571  * @param f The functor to unblock.
572  * @note If the same functor has been connected more than once to the
573  * same EmitterArg object, this call will unblock all of them.
574  */
576 
577 /**
578  * @exception std::bad_alloc The constructor might throw
579  * std::bad_alloc if memory is exhausted and the system throws in that
580  * case.
581  */
582  EmitterArg() = default;
583 
584 /**
585  * This class cannot be copied. The copy constructor is deleted.
586  */
587  EmitterArg(const EmitterArg&) = delete;
588 
589 /**
590  * This class cannot be copied. The assignment operator is deleted.
591  */
592  EmitterArg& operator=(const EmitterArg&) = delete;
593 
594 /**
595  * The destructor does not throw provided that the destructors of any
596  * bound arguments do not throw (as they should not do), and assuming
597  * that merely iterating through a list does not throw (as it would
598  * not on any sane implementation).
599  */
600  ~EmitterArg();
601 
602 /* Only has effect if --with-glib-memory-slices-compat or
603  * --with-glib-memory-slices-no-compat option picked */
605 };
606 
607 template <class... FreeArgs>
609 
610  // gcc-4.4 and 4.5 don't support this:
611  /*
612  for(const ListItem& l: emission_list) {l.f2();}
613  */
614  // gcc-4.4 doesn't support this;
615  /*
616  std::for_each(emission_list.begin(), emission_list.end(),
617  [](const ListItem& l){(l.f2)();});
618  */
619  // So do it the old way:
620  struct DisconnectReleaserItem {
621  static void exec(const ListItem& l) {(l.f2)();}
622  };
623  std::for_each(emission_list.begin(), emission_list.end(),
625 }
626 
627 template <class... FreeArgs>
629 
630  // create a local copy of emission_list, to enable a connected
631  // function (i) to delete the EmitterArg<> object to which it is
632  // connected, even if there are other functors still to execute in
633  // the same emission (which will execute normally provided they do
634  // not try to call any of the emitter's functions), (ii) to call
635  // 'delete this' nothwithstanding that the connected function is
636  // protected by a Releaser object (assuming all the other restraints
637  // on calling 'delete this' are met), provided that no other access
638  // would be made to the deleted object in a function call connected
639  // to the same emitter which is due to execute subsequently in the
640  // same emission, and (iii) to disconnect itself from the
641  // EmitterArg object. This design approach has a trade-off: if a
642  // connected function tries to block, unblock or disconnect another
643  // function connected to the same EmitterArg<> object which is due
644  // to execute subsequently in the same emission (or to block,
645  // unblock or disconnect itself when it is due to execute again
646  // subsequently in the same emission), the attempted block, unblock
647  // or disconnection will not have any effect on that emission (it
648  // will only have effect on a subsequent emission). In addition, a
649  // connected function may not destroy an object whose non-static
650  // method is connected to the same emitter and which would execute
651  // subsequently in the same emission, even if that object is
652  // protected by a Releaser object (the non-static method will
653  // unsuccessfully attempt to execute notwithstanding the destruction
654  // of the object it would be operating on).
655 
656  // we can't use uniform initialisation here as it would be
657  // construed as invoking an initialiser list with a list item,
658  // rather than passing an already formed list
659  std::list<ListItem> local_list = emission_list;
660 
661 /*
662  gcc-4.4 doesn't support lambdas, gcc-4.5 doesn't like lambda
663  captures which comprise variadic arguments, and neither support
664  range-based for, so iterate by hand
665 */
666  typename std::list<ListItem>::const_iterator iter;
667  for (iter = local_list.begin(); iter != local_list.end(); ++iter) {
668  if (!iter->blocked) iter->f1(args...);
669  }
670 }
671 
672 template <class... FreeArgs>
674  if (emission_list.empty()) return false;
675  emit(args...);
676  return true;
677 }
678 
679 template <class... FreeArgs>
681  emission_list.emplace_back(f1, Callback::Functor());
682  return f1;
683 }
684 
685 template <class... FreeArgs>
687  // In this method:
688  // f1 is the functor we execute when we emit()
689  // f2 is the functor we execute in our destructor if we are destroyed before the
690  // remote object is
691  // f3 is the functor the remote object executes in its Releaser if it is destroyed
692  // before we are, or if Releaser::operator=() is called
693 
695  Callback::Functor f2{Callback::make_ref(r, &Releaser::remove, f3)};
696  r.add(f3);
697  try {
698  emission_list.emplace_back(f1, f2);
699  }
700  catch (...) {
701  r.remove(f3);
702  throw;
703  }
704  return f1;
705 }
706 
707 template <class... FreeArgs>
709  // in theory, we could have connected the same functor object
710  // more than once, so cater for that
711  auto iter = emission_list.begin();
712  for (;;) {
713  // gcc-4.4 doesn't support lambdas:
714  /*
715  iter = std::find_if(iter, emission_list.end(),
716  [&arg](const ListItem& p) -> bool {return p.f1 == arg;});
717  */
718  // so use a local struct and std::bind:
719  struct Pred {
720  static bool pred(const ListItem& p, const Callback::FunctorArg<FreeArgs...>& f) {
721  return (p.f1 == f);
722  }
723  };
724  iter = std::find_if(iter, emission_list.end(),
725  std::bind(Pred::pred, std::placeholders::_1, std::ref(arg)));
726  if (iter != emission_list.end()) {
727  // remove ourselves from the remote Releaser object
728  (iter->f2)();
729 
730  // remove this item from emission_list
731  iter = emission_list.erase(iter);
732  }
733  else break;
734  }
735 }
736 
737 // tracking disconnect() is the same as disconnect(), except that we do not
738 // execute f2 as the remote Releaser object will destroy its own functors
739 // in that case
740 template <class... FreeArgs>
742  auto iter = emission_list.begin();
743  for (;;) {
744  // gcc-4.4 doesn't support lambdas:
745  /*
746  iter = std::find_if(iter, emission_list.end(),
747  [&arg](const ListItem& p) -> bool {return p.f1 == arg;});
748  */
749  // so use a local struct and std::bind:
750  struct Pred {
751  static bool pred(const ListItem& p, const Callback::FunctorArg<FreeArgs...>& f) {
752  return (p.f1 == f);
753  }
754  };
755  iter = std::find_if(iter, emission_list.end(),
756  std::bind(Pred::pred, std::placeholders::_1, std::ref(arg)));
757  if (iter != emission_list.end()) {
758  // remove this item from emission_list
759  iter = emission_list.erase(iter);
760  }
761  else break;
762  }
763 }
764 
765 template <class... FreeArgs>
767  // in theory, we could have connected the same functor object
768  // more than once, so cater for that
769  auto iter = emission_list.begin();
770  for (;;) {
771  // gcc-4.4 doesn't support lambdas:
772  /*
773  iter = std::find_if(iter, emission_list.end(),
774  [&arg](const ListItem& p) -> bool {return p.f1 == arg;});
775  */
776  // so use a local struct and std::bind:
777  struct Pred {
778  static bool pred(const ListItem& p, const Callback::FunctorArg<FreeArgs...>& f) {
779  return (p.f1 == f);
780  }
781  };
782  iter = std::find_if(iter, emission_list.end(),
783  std::bind(Pred::pred, std::placeholders::_1, std::ref(arg)));
784  if (iter != emission_list.end()) {
785  iter->blocked = true;
786  ++iter;
787  }
788  else break;
789  }
790 }
791 
792 template <class... FreeArgs>
794  // in theory, we could have connected the same functor object
795  // more than once, so cater for that
796  auto iter = emission_list.begin();
797  for (;;) {
798  // gcc-4.4 doesn't support lambdas:
799  /*
800  iter = std::find_if(iter, emission_list.end(),
801  [&arg](const ListItem& p) -> bool {return p.f1 == arg;});
802  */
803  // so use a local struct and std::bind:
804  struct Pred {
805  static bool pred(const ListItem& p, const Callback::FunctorArg<FreeArgs...>& f) {
806  return (p.f1 == f);
807  }
808  };
809  iter = std::find_if(iter, emission_list.end(),
810  std::bind(Pred::pred, std::placeholders::_1, std::ref(arg)));
811  if (iter != emission_list.end()) {
812  iter->blocked = false;
813  ++iter;
814  }
815  else break;
816  }
817 }
818 
819 /**
820  * @class SafeEmitterArg emitter.h c++-gtk-utils/emitter.h
821  * @brief A thread-safe class to execute callbacks connected to it,
822  * with provision for automatic disconnection.
823  * @sa EmitterArg Releaser
824  * @sa emitter.h
825  * @sa Callback namespace
826  *
827  * This is a thread-safe version of the EmitterArg class.
828  * Callback::SafeFunctorArg objects may be connected to SafeEmitter
829  * classes, and will be executed when SafeEmitterArg::emit() or
830  * SafeEmitterArg::operator()() are called.
831  *
832  * One version of the connect() method takes a Releaser object as an
833  * argument. Such a Releaser object should be a public member of any
834  * target class which wants functors representing (or calling into)
835  * any of its methods to be disconnected automatically from the
836  * SafeEmitterArg object when the target class object is destroyed.
837  *
838  * A connection may be explicitly disconnected by calling the
839  * disconnect() method, and may also be temporarily blocked and
840  * subsequently unblocked with the block() and unblock() methods.
841  *
842  * The template types are the types of the unbound arguments, if any.
843  * SafeEmitterArg<> is typedef'ed to SafeEmitter.
844  *
845  * @b Usage
846  *
847  * These are examples:
848  *
849  * @code
850  * using namespace Cgu;
851  *
852  * SafeEmitter se1;
853  * se1.connect(Callback::lambda<>([] () {std::cout << "Hello world\n";}));
854  * se1();
855  *
856  * int res;
857  * SafeEmitterArg<int, int&> se2;
858  * se2.connect(Callback::lambda<int, int&>([] (int i, int& j) {j = 10 * i;}));
859  * se2(2, res);
860  * std::cout << "10 times 2 is " << res << '\n';
861  * @endcode
862  *
863  * For further background, including about thread-safety and exception
864  * safety and other matters, read this: emitter.h, or for more
865  * information about bound and unbound arguments, read this:
866  * Cgu::Callback.
867  */
868 
869 template <class... FreeArgs>
870 class SafeEmitterArg {
871 
872 #ifndef DOXYGEN_PARSING
873  // f1 is the functor we execute when we emit()
874  // f2 is the functor we execute in our destructor if we are destroyed
875  // before the remote object is
876  struct ListItem {
877  Callback::SafeFunctorArg<FreeArgs...> f1;
879  bool blocked;
881  f1(f1_), f2(f2_), blocked(false) {}
882  };
883 #endif
884 
885  std::list<ListItem> emission_list;
886  mutable Thread::Mutex mutex; // make this mutable so we can lock/unlock in const methods
887 
888  // only Releaser objects can access this
889  void tracking_disconnect(const Callback::SafeFunctorArg<FreeArgs...>&);
890 
891 public:
892  friend class Releaser;
893 
894 /**
895  * This will execute the connected functors. It is thread safe if the
896  * functions or class methods referenced by the connected functors are
897  * thread safe.
898  * @param args The unbound arguments to be passed to the referenced
899  * function or class method, if any.
900  * @exception std::bad_alloc The method might throw std::bad_alloc if
901  * memory is exhausted and the system throws in that case. In
902  * addition, it will throw if the functions or class methods
903  * referenced by the functors throw (or if the copy constructor of a
904  * free or bound argument throws and it is not a reference argument).
905  */
906  void operator()(typename Cgu::Param<FreeArgs>::ParamType... args) const {emit(args...);}
907 
908 /**
909  * This will execute the connected functors. It is thread safe if the
910  * functions or class methods referenced by the connected functors are
911  * thread safe.
912  * @param args The unbound arguments to be passed to the referenced
913  * function or class method, if any.
914  * @exception std::bad_alloc The method might throw std::bad_alloc if
915  * memory is exhausted and the system throws in that case. In
916  * addition, it will throw if the functions or class methods
917  * referenced by the functors throw (or if the copy constructor of a
918  * free or bound argument throws and it is not a reference argument).
919  */
920  void emit(typename Cgu::Param<FreeArgs>::ParamType... args) const;
921 
922 /**
923  * This will execute the connected functors, but it also reports
924  * whether in fact there were any connected functors to execute. It
925  * is thread safe if the functions or class methods referenced by the
926  * connected functors are thread safe. (It is not necessary to use
927  * this function just because it is not known whether a functor is
928  * connected - if the standard emit() function is called when no
929  * functor is connected, nothing will happen. The feature of this
930  * method is that it will report the outcome.)
931  * @param args The unbound arguments to be passed to the referenced
932  * function or class method, if any.
933  * @return Returns false if there were no functors to execute, or true
934  * if functors have been executed.
935  * @exception std::bad_alloc The method might throw std::bad_alloc if
936  * memory is exhausted and the system throws in that case. In
937  * addition, it will throw if the functions or class methods
938  * referenced by the functors throw (or if the copy constructor of a
939  * free or bound argument throws and it is not a reference argument).
940  */
941  bool test_emit(typename Cgu::Param<FreeArgs>::ParamType... args) const;
942 
943 /**
944  * Connects a functor. It is thread safe.
945  * @param f The functor to connect.
946  * @return The functor connected.
947  * @exception std::bad_alloc The method might throw std::bad_alloc if
948  * memory is exhausted and the system throws in that case.
949  */
951 
952 /**
953  * Connects a functor. It is thread safe.
954  * @param f The functor to connect.
955  * @param r A Releaser object for automatic disconnection of the
956  * functor if the object whose method it represents is destroyed.
957  * @return The functor connected.
958  * @exception std::bad_alloc The method might throw std::bad_alloc if
959  * memory is exhausted and the system throws in that case.
960  */
962 
963 /**
964  * Disconnects a functor previously connected. This does not throw
965  * provided that the destructors of any bound arguments do not throw
966  * (as they should not do), and assuming that merely iterating through
967  * a list does not throw (as it would not on any sane implementation).
968  * It is thread safe.
969  * @param f The functor to disconnect.
970  * @note If the same functor has been connected more than once to the
971  * same SafeEmitterArg object, this call will disconnect all of them.
972  */
974 
975 /**
976  * Blocks a connected functor from executing when emit() or
977  * operator()() is called until unblock() is called. This method does
978  * not throw (assuming that merely iterating through a list does not
979  * throw, as it would not on any sane implementation). It is thread
980  * safe.
981  * @param f The functor to block.
982  * @note If the same functor has been connected more than once to the
983  * same SafeEmitterArg object, this call will block all of them.
984  */
986 
987 /**
988  * Unblocks a previously blocked functor. This method does not throw
989  * (assuming that merely iterating through a list does not throw, as
990  * it would not on any sane implementation). It is thread safe.
991  * @param f The functor to unblock.
992  * @note If the same functor has been connected more than once to the
993  * same SafeEmitterArg object, this call will unblock all of them.
994  */
996 
997 /**
998  * @exception std::bad_alloc The constructor might throw
999  * std::bad_alloc if memory is exhausted and the system throws in that
1000  * case.
1001  * @exception Thread::MutexError The constructor might throw
1002  * Thread::MutexError if initialisation of the contained mutex fails.
1003  * (It is often not worth checking for this, as it means either memory
1004  * is exhausted or pthread has run out of other resources to create
1005  * new mutexes.)
1006  */
1007  SafeEmitterArg() = default;
1008 
1009 /**
1010  * This class cannot be copied. The copy constructor is deleted.
1011  */
1012  SafeEmitterArg(const SafeEmitterArg&) = delete;
1013 
1014 /**
1015  * This class cannot be copied. The assignment operator is deleted.
1016  */
1017  SafeEmitterArg& operator=(const SafeEmitterArg&) = delete;
1018 
1019 /**
1020  * The destructor does not throw provided that the destructors of any
1021  * bound arguments do not throw (as they should not do), and assuming
1022  * that merely iterating through a list does not throw (as it would
1023  * not on any sane implementation). It is thread-safe as regards the
1024  * dropping of any connected functors and of any relevant Releaser
1025  * objects.
1026  */
1027  ~SafeEmitterArg();
1028 
1029 /* Only has effect if --with-glib-memory-slices-compat or
1030  * --with-glib-memory-slices-no-compat option picked */
1032 };
1033 
1034 template <class... FreeArgs>
1036 
1037  // go through emission_list() item by item, popping off the front and erasing
1038  // as we go in case Releaser::try_remove() fails to acquire the lock on one
1039  // of the iterations
1040  Thread::Mutex::Lock lock{mutex};
1041  while (!emission_list.empty()) {
1042  auto iter = emission_list.begin();
1043  int result = 0; // f2 might be a no-op
1044  // remove ourselves from the remote Releaser object
1045  (iter->f2)(&result);
1046  if (!result) { // we got the Releaser mutex lock or no-op
1047  // now remove this item from emission_list
1048  emission_list.erase(iter);
1049  }
1050  else {
1051  mutex.unlock();
1052  // spin nicely
1053 #ifdef CGU_USE_SCHED_YIELD
1054  sched_yield();
1055 #else
1056  usleep(10);
1057 #endif
1058  mutex.lock();
1059  }
1060  }
1061 }
1062 
1063 template <class... FreeArgs>
1065 
1066  // create a local copy of emission_list, to enable a connected
1067  // function (i) to delete the EmitterArg<> object to which it is
1068  // connected, even if there are other functors still to execute in
1069  // the same emission (which will execute normally provided they do
1070  // not try to call any of the emitter's functions), (ii) to call
1071  // 'delete this' nothwithstanding that the connected function is
1072  // protected by a Releaser object (assuming all the other restraints
1073  // on calling 'delete this' are met), provided that no other access
1074  // would be made to the deleted object in a function call connected
1075  // to the same emitter which is due to execute subsequently in the
1076  // same emission, and (iii) to disconnect itself from the
1077  // EmitterArg<> object. This design approach has a trade-off: if a
1078  // connected function tries to block, unblock or disconnect another
1079  // function connected to the same EmitterArg<> object which is due
1080  // to execute subsequently in the same emission (or to block,
1081  // unblock or disconnect itself when it is due to execute again
1082  // subsequently in the same emission), the attempted block, unblock
1083  // or disconnection will not have any effect on that emission (it
1084  // will only have effect on a subsequent emission). In addition, a
1085  // connected function may not destroy an object whose non-static
1086  // method is connected to the same emitter and which would execute
1087  // subsequently in the same emission, even if that object is
1088  // protected by a Releaser object (the non-static method will
1089  // unsuccessfully attempt to execute notwithstanding the destruction
1090  // of the object it would be operating on).
1091 
1092  // SafeFunctorArg usage has the additional point that while an
1093  // emission is in course, another thread should not try to do any of
1094  // those things, or the same outcome will result. Another thread
1095  // should leave alone objects connected to a SafeEmitterArg<> object
1096  // from the time of operator()() or emit() beginning to the time of
1097  // it ending, and not try to interfere.
1098 
1099  // a side effect of having a local list is that, as required, we
1100  // will not be holding our mutex when executing the functors it
1101  // contains. It is OK having the functors in two different lists
1102  // which are potentially (when our mutex is released) in two
1103  // different threads, because the functors hold their
1104  // Callback::Callback objects by SharedLockPtr so their reference
1105  // count is protected (they are SafeFunctorArg<> functors).
1106 
1107  // we could reduce contention on the mutex by allocating local_list
1108  // outside the mutex, eg by taking the size of emission_list within
1109  // the mutex, then allocating the nodes of local_list outside the
1110  // mutex with that size, and then copying items across within the
1111  // mutex (checking the end iterators of both containers when
1112  // iterating because the size of emitter_list could have changed
1113  // while allocating local_list) and, if the size of emission list
1114  // did change by another thread disconnecting a functor in the
1115  // interval when local_list was allocated, resizing local_list
1116  // downwards with std::list::resize(). However this is mostly
1117  // pointless, because although this arrangement would be as equally
1118  // thread-safe as the implementation below and lessen contention,
1119  // since you don't know exactly what functors will be executed
1120  // anyway if functors are added or removed by one thread while
1121  // another is emitting, such concurrent emitting is not a practice
1122  // to make special provision for. Accordingly, we go the simpler,
1123  // more naive route below.
1124 
1125  std::list<ListItem> local_list;
1126  { // scope block for mutex lock
1127  Thread::Mutex::Lock lock{mutex};
1128  local_list = emission_list;
1129  }
1130 
1131 /*
1132  gcc-4.4 doesn't support lambdas, gcc-4.5 doesn't like lambda
1133  captures which comprise variadic arguments, and neither support
1134  range-based for, so iterate by hand
1135 */
1136  typename std::list<ListItem>::const_iterator iter;
1137  for (iter = local_list.begin(); iter != local_list.end(); ++iter) {
1138  if (!iter->blocked) iter->f1(args...);
1139  }
1140 }
1141 
1142 template <class... FreeArgs>
1144 
1145  std::list<ListItem> local_list;
1146  { // scope block for mutex lock
1147  Thread::Mutex::Lock lock{mutex};
1148  if (emission_list.empty()) return false;
1149  local_list = emission_list;
1150  }
1151 
1152 /*
1153  gcc-4.4 doesn't support lambdas, gcc-4.5 doesn't like lambda
1154  captures which comprise variadic arguments, and neither support
1155  range-based for, so iterate by hand
1156 */
1157  typename std::list<ListItem>::const_iterator iter;
1158  for (iter = local_list.begin(); iter != local_list.end(); ++iter) {
1159  if (!iter->blocked) iter->f1(args...);
1160  }
1161  return true;
1162 }
1163 
1164 template <class... FreeArgs>
1166  // construct the new node outside the mutex to reduce contention and
1167  // then splice it at the end
1168  std::list<ListItem> tmp{ListItem{f1, Callback::SafeFunctorArg<int*>()}};
1169  Thread::Mutex::Lock lock{mutex};
1170  emission_list.splice(emission_list.end(), std::move(tmp));
1171  return f1;
1172 }
1173 
1174 template <class... FreeArgs>
1176  // In this method:
1177  // f1 is the functor we execute when we emit()
1178  // f2 is the functor we execute in our destructor if we are destroyed before the
1179  // remote object is
1180  // f3 is the functor the remote object executes in its Releaser if it is destroyed
1181  // before we are, or if Releaser::operator=() is called
1182 
1184  Callback::SafeFunctorArg<int*> f2{Callback::make_ref(r, &Releaser::try_remove, f3)};
1185  // we can't call Releaser::add() when holding our mutex or we will
1186  // get out of order locking, as Releaser's mutex is acquired in that
1187  // method, and we don't need to do so
1188  r.add(f3);
1189  try {
1190  // construct the new node outside the mutex to reduce contention
1191  // and then splice it at the end
1192  std::list<ListItem> tmp{ListItem{f1, f2}};
1193  Thread::Mutex::Lock lock{mutex};
1194  emission_list.splice(emission_list.end(), std::move(tmp));
1195  }
1196  catch (...) {
1197  r.remove(f3);
1198  throw;
1199  }
1200  return f1;
1201 }
1202 
1203 template <class... FreeArgs>
1205  // in theory, we could have connected the same functor object more than
1206  // once, so cater for that as well as Releaser::try_remove() failing
1207  Thread::Mutex::Lock lock{mutex};
1208  auto iter = emission_list.begin();
1209  for(;;) {
1210  /*
1211  // gcc-4.4 doesn't support lambdas:
1212  iter = std::find_if(iter, emission_list.end(),
1213  [&arg](const ListItem& p) -> bool {return p.f1 == arg;});
1214  */
1215  // so use a local struct and std::bind:
1216  struct Pred {
1217  static bool pred(const ListItem& p, const Callback::SafeFunctorArg<FreeArgs...>& f) {
1218  return (p.f1 == f);
1219  }
1220  };
1221  iter = std::find_if(iter, emission_list.end(),
1222  std::bind(Pred::pred, std::placeholders::_1, std::ref(arg)));
1223  if (iter != emission_list.end()) {
1224  int result = 0; // f2 might be a no-op
1225  // remove ourselves from the remote Releaser object
1226  (iter->f2)(&result);
1227  if (!result) { // we got the Releaser mutex lock or no-op
1228  // now remove this item from emission_list
1229  iter = emission_list.erase(iter);
1230  }
1231  else {
1232  mutex.unlock();
1233  // spin nicely
1234 #ifdef CGU_USE_SCHED_YIELD
1235  sched_yield();
1236 #else
1237  usleep(10);
1238 #endif
1239  mutex.lock();
1240  // start again at the beginning - we have released the mutex
1241  // so our iterator may have become invalid
1242  iter = emission_list.begin();
1243  }
1244  }
1245  else break;
1246  }
1247 }
1248 
1249 // tracking disconnect() is the same as disconnect(), except that we do not
1250 // execute f2 as the remote Releaser object will destroy its own functors
1251 // in that case
1252 template <class... FreeArgs>
1254  Thread::Mutex::Lock lock{mutex};
1255  auto iter = emission_list.begin();
1256  for (;;) {
1257  // gcc-4.4 doesn't support lambdas:
1258  /*
1259  iter = std::find_if(iter, emission_list.end(),
1260  [&arg](const ListItem& p) -> bool {return p.f1 == arg;});
1261  */
1262  // so use a local struct and std::bind:
1263  struct Pred {
1264  static bool pred(const ListItem& p, const Callback::SafeFunctorArg<FreeArgs...>& f) {
1265  return (p.f1 == f);
1266  }
1267  };
1268  iter = std::find_if(iter, emission_list.end(),
1269  std::bind(Pred::pred, std::placeholders::_1, std::ref(arg)));
1270  if (iter != emission_list.end()) {
1271  // remove this item from emission_list
1272  iter = emission_list.erase(iter);
1273  }
1274  else break;
1275  }
1276 }
1277 
1278 template <class... FreeArgs>
1280  // in theory, we could have connected the same functor object
1281  // more than once, so cater for that
1282  Thread::Mutex::Lock lock{mutex};
1283  auto iter = emission_list.begin();
1284  for (;;) {
1285  // gcc-4.4 doesn't support lambdas:
1286  /*
1287  iter = std::find_if(iter, emission_list.end(),
1288  [&arg](const ListItem& p) -> bool {return p.f1 == arg;});
1289  */
1290  // so use a local struct and std::bind:
1291  struct Pred {
1292  static bool pred(const ListItem& p, const Callback::SafeFunctorArg<FreeArgs...>& f) {
1293  return (p.f1 == f);
1294  }
1295  };
1296  iter = std::find_if(iter, emission_list.end(),
1297  std::bind(Pred::pred, std::placeholders::_1, std::ref(arg)));
1298  if (iter != emission_list.end()) {
1299  iter->blocked = true;
1300  ++iter;
1301  }
1302  else break;
1303  }
1304 }
1305 
1306 template <class... FreeArgs>
1308  // in theory, we could have connected the same functor object
1309  // more than once, so cater for that
1310  Thread::Mutex::Lock lock{mutex};
1311  auto iter = emission_list.begin();
1312  for (;;) {
1313  // gcc-4.4 doesn't support lambdas:
1314  /*
1315  iter = std::find_if(iter, emission_list.end(),
1316  [&arg](const ListItem& p) -> bool {return p.f1 == arg;});
1317  */
1318  // so use a local struct and std::bind:
1319  struct Pred {
1320  static bool pred(const ListItem& p, const Callback::SafeFunctorArg<FreeArgs...>& f) {
1321  return (p.f1 == f);
1322  }
1323  };
1324  iter = std::find_if(iter, emission_list.end(),
1325  std::bind(Pred::pred, std::placeholders::_1, std::ref(arg)));
1326  if (iter != emission_list.end()) {
1327  iter->blocked = false;
1328  ++iter;
1329  }
1330  else break;
1331  }
1332 }
1333 
1334 } // namespace Cgu
1335 
1336 #endif // EMITTER_H