c++-gtk-utils
emitter.h
Go to the documentation of this file.
1 /* Copyright (C) 2009 to 2011 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 function. The Releaser object should be passed as
70  * the second argument of EmitterArg::connect(). As well as a
71  * Releaser object informing an emitter object when it has ceased to
72  * exist, an emitter object will do the same to the Releaser object if
73  * the emitter object happens to be destroyed before an object whose
74  * members it references (and therefore before the Releaser object).
75  * Automatic disconnection is mainly useful for non-static member
76  * functions, but it can be employed for static member functions or
77  * non-member functions if wanted (that will in effect bind the
78  * lifetime of the functor to that of the object to whose Releaser the
79  * functor has 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  * @b Alternatives
135  *
136  * These classes are intended as a lightweight thread-safe signal/slot
137  * mechanism for GUI programming. For more demanding usage libsigc++
138  * is a good choice, except that it is not thread-safe. An
139  * alternative to libsigc++ is the boost::signal2 module, which is
140  * thread-safe.
141  *
142  * @b Subsidiary @b thread-safety @b points
143  *
144  * As mentioned, the SafeEmitterArg classes are thread safe, and their
145  * methods can be called in different threads without ill effect.
146  * However, there are some things that cannot be done. Users should
147  * observe two points.
148  *
149  * First, it has been mentioned that if a connected function blocks,
150  * unblocks or disconnects another function connected to the same
151  * emitter object and due to execute subsequently in the same
152  * emission, the blocking, unblocking or disconnection will not have
153  * effect in that emission, and that a connected function may not
154  * delete an object whose non-static method is due to execute
155  * subsequently in the same emission. The same outcome would result
156  * if another thread tries to do any of these things while an emission
157  * is under way. Another thread should therefore leave alone objects
158  * connected to a SafeEmitterArg object from the time of operator()()
159  * or emit() beginning to the time of it ending, and not try to
160  * interfere.
161  *
162  * Secondly, when a Releaser object is passed as the second argument
163  * to the connect() method of a SafeEmitterArg object, the Releaser
164  * object must remain in existence until the connect() method returns
165  * or the emitter may be left in an inconsistent state.
166  *
167  * @anchor AssignmentAnchor
168  * @b Assignment
169  *
170  * EmitterArg and SafeEmitterArg objects cannot be copied. Releaser
171  * objects can be (we do not want to make a class uncopiable just
172  * because it has the safety feature of having a Releaser object as a
173  * member).
174  *
175  * So how should assignment of a Releaser object and of a class which
176  * has a Releaser as a member be handled? An object which has a
177  * Releaser as a member and which is being assigned to (the assignee)
178  * could keep all its existing pre-assignment emitter connections - so
179  * far as the Releaser object is concerned, it will have to do so
180  * where the connections are not protected by the Releaser object, and
181  * we could do the same in relation to protected connections, in which
182  * case we would make operator=() of Releaser do nothing: that is,
183  * just return - a default assignment would always be wrong as it
184  * would take the assignor's Releaser state but inherit none of its
185  * connections, which the assignee cannot inherit as they depend on a
186  * remote emitter object or objects.
187  *
188  * However, the state of the assignee after assignment may not be such
189  * as to permit the inheriting of all the assignor's state except its
190  * connections. Accordingly, the default strategy adopted here is for
191  * the Releaser object to become a blank sheet on assignment. After
192  * assignment, an assignee which has a Releaser object as a member
193  * will no longer have any of the emitter connections which were,
194  * prior to assignment, protected by the Releaser object. If in a
195  * particular case the user does not want this behaviour, she should
196  * provide an assignment operator in the class which has Releaser as a
197  * member and leave Releaser alone in the assignment operator.
198  *
199  * @b Usage
200  *
201  * For an object my_obj of class type MyClass, with a method void
202  * MyClass::my_method(int, int, const char*), usage for a fully bound
203  * functor and emitter would be:
204  *
205  * @code
206  * using namespace Cgu;
207  * int arg1 = 1, arg2 = 5;
208  * Emitter e;
209  * e.connect(Callback::make(my_obj, &MyClass::my_method, arg1, arg2, "Hello\n"));
210  * e();
211  *
212  * SafeEmitter se;
213  * se.connect(Callback::make(my_obj, &MyClass::my_method, arg1, arg2, "Hello\n"));
214  * se();
215  * @endcode
216  *
217  * Or for a partially bound functor and emitter:
218  *
219  * @code
220  * using namespace Cgu;
221  * int arg1 = 1, arg2 = 5;
222  * EmitterArg<int, const char*> e;
223  * e.connect(Callback::make(my_obj, &MyClass::my_method, arg1));
224  * e(arg2, "Hello\n");
225  *
226  * SafeEmitterArg<int, const char*> se;
227  * se.connect(Callback::make(my_obj, &MyClass::my_method, arg1));
228  * se(arg2, "Hello\n");
229  * @endcode
230  *
231  * EmitterArg classes do not provide for a return value. If a
232  * result is wanted, users should pass an unbound argument by
233  * reference or pointer (or pointer to pointer).
234  *
235  * CallbackArg (and so FunctorArg and EmitterArg) objects can be
236  * constructed for up to three bound arguments and an unlimited number
237  * of unbound arguments, or from std::function objects (in which case
238  * there is no limit to the number of bound arguments nor their
239  * ordering with unbound arguments). See Cgu::Callback for further
240  * details.
241  *
242  * @b Exception @b safety
243  *
244  * Apart from the emit()/operator()() and connect() methods, nothing
245  * done to an EmitterArg/SafeEmitterArg object should cause an
246  * exception to be thrown. This is because other methods only iterate
247  * through a std::list object using std::for_each(), std::find() or by
248  * hand, and the only things done by std::for_each() or after a
249  * std::find() or iteration is to remove a functor from the list
250  * (copying a functor and comparing functors never throw, nor does
251  * destroying a functor provided the destructors of any bound argument
252  * type do not throw). Thus, an EmitterArg/SafeEmitterArg and
253  * Releaser object should never get into an inconsistent state.
254  *
255  * The connect() method could throw a std::bad_alloc exception, either
256  * on creating new functors or on pushing the functors onto the list.
257  * However, were it to do so, the method has strong exception safety
258  * (assuming merely iterating over a list does not throw, as it should
259  * not).
260  *
261  * The emit()/operator()() methods could throw std::bad_alloc, and so
262  * far as that is concerned emission of all the connected functions
263  * will either all succeed or all fail. In addition, the connected
264  * functions referenced by the functors held by the emitter might
265  * throw when executed. emit()/operator()() do not attempt to catch
266  * these exceptions as there is nothing they could do with them. This
267  * means that although a throwing connected function will not leave
268  * the EmitterArg/SafeEmitterArg object in an inconsistent state, any
269  * other connected functions due to execute subsequently on that same
270  * emission will not execute. If that is important in any particular
271  * case, the user must incorporate logic in the connected functions to
272  * cater for an exception causing only part execution, or must connect
273  * only one function to any one signal and "chain" emissions by hand
274  * so as to do the right thing.
275  */
276 
277 /*
278  Mutex locking heirarchy:
279 
280  Some out-of-order locking must take place because of the
281  relationship between the Releaser and SafeEmitterArg<> classes. The
282  mutex of Releaser is given the higher priority. This means that a
283  plain EmitterArg<> object will not take any hit from the fact that
284  Releaser is also useable with SafeEmitterArg<> objects.
285 
286  One consequence is that to avoid deadlocks, it is the
287  SafeEmitterArg<> functions which must yield when a deadlock would
288  otherwise arise. Yielding could occur in
289  SafeEmitterArg<>::~SafeEmitterArg() and
290  SafeEmitterArg<>::disconnect().
291 */
292 
293 #ifdef CGU_USE_SCHED_YIELD
294 #include <sched.h>
295 #else
296 #include <unistd.h>
297 #endif
298 
299 #include <list>
300 #include <unordered_set>
301 #include <algorithm>
302 #include <functional>
303 
304 #include <c++-gtk-utils/callback.h>
305 #include <c++-gtk-utils/mutex.h>
307 
308 namespace Cgu {
309 
310 /* The four basic emitter types */
311 
312 template <class... FreeArgs> class EmitterArg;
313 template <class... FreeArgs> class SafeEmitterArg;
314 typedef EmitterArg<> Emitter;
316 
317 /**
318  * @class Releaser emitter.h c++-gtk-utils/emitter.h
319  * @brief A class used for tracking EmitterArg and SafeEmitterArg
320  * connections.
321  * @sa EmitterArg SafeEmitterArg
322  * @sa emitter.h
323  * @sa Callback namespace
324  *
325  * This class provides tracking of EmitterArg and SafeEmitterArg
326  * connections. It should be a public member of any target class
327  * which wants functors representing any of its methods to be
328  * disconnected automatically from an EmitterArg or SafeEmitterArg
329  * object when the target class object is destroyed, and is passed as
330  * one of the arguments to the connect() method of EmitterArg or
331  * SafeEmitterArg.
332  *
333  * All its methods are thread-safe.
334  *
335  * For further background, read this: emitter.h
336  */
337 
338 class Releaser {
339 
340  // from version 2.0.0-rc3 we use std::unordered_set rather than
341  // std::list in Releaser. We can't do that for
342  // EmitterArg/SafeEmitterArg objects, as they need to execute
343  // connected functors in the order in which they were connected.
344  std::unordered_set<Callback::SafeFunctor> disconnect_set;
345  Thread::Mutex mutex;
346 
347  // only an EmitterArg or SafeEmitterArg object can access add(), remove and try_remove()
348  void add(const Callback::SafeFunctor&);
349  void remove(const Callback::SafeFunctor&);
350  void try_remove(const Callback::SafeFunctor&, int*);
351 public:
352  template <class... T> friend class EmitterArg;
353  template <class... T> friend class SafeEmitterArg;
354 
355  // operator=() and the copy constructor should copy nothing from the
356  // assignor, because disconnect_set should be empty in the
357  // assignee, as any class containing us does not acquire as assignee
358  // any emitter functors representing any of its methods
359 
360 /**
361  * See notes on @ref AssignmentAnchor "assignment" to see how this
362  * operates. This does not throw provided that the destructors of any
363  * bound arguments of a functor managed by this Releaser object prior
364  * to assignment do not throw (as they should not do), and assuming
365  * that merely iterating through a list does not throw (as it would
366  * not on any sane implementation).
367  * @param r The assignee.
368  */
369  Releaser& operator=(const Releaser& r);
370 
371 /**
372  * This does not copy anything from the Releaser object passed as an
373  * argument - see the notes on @ref AssignmentAnchor "assignment" for
374  * an explanation of why. This does not throw.
375  * @param r A Releaser object.
376  * @exception std::bad_alloc This constructor might throw
377  * std::bad_alloc if memory is exhausted and the system throws in that
378  * case.
379  * @exception Thread::MutexError This constructor might throw
380  * Thread::MutexError if initialisation of the contained mutex fails.
381  * (It is often not worth checking for this, as it means either memory
382  * is exhausted or pthread has run out of other resources to create
383  * new mutexes.)
384  */
385  Releaser(const Releaser& r) {}
386 
387 /**
388  * @exception std::bad_alloc The default constructor might throw
389  * std::bad_alloc if memory is exhausted and the system throws in that
390  * case.
391  * @exception Thread::MutexError The default constructor might throw
392  * Thread::MutexError if initialisation of the contained mutex fails.
393  * (It is often not worth checking for this, as it means either memory
394  * is exhausted or pthread has run out of other resources to create
395  * new mutexes.)
396  */
397  Releaser() = default;
398 
399 /**
400  * The destructor does not throw provided that the destructors of any
401  * bound arguments of a functor managed by this Releaser object do not
402  * throw (as they should not do), and assuming that merely iterating
403  * through an unordered_set does not throw (as it would not on any
404  * sane implementation).
405  */
406  ~Releaser();
407 
408 /* Only has effect if --with-glib-memory-slices-compat or
409  * --with-glib-memory-slices-no-compat option picked */
411 };
412 
413 /* the emitter classes */
414 
415 /**
416  * @class EmitterArg emitter.h c++-gtk-utils/emitter.h
417  * @brief A class to execute callbacks connected to it, with provision
418  * for automatic disconnection.
419  * @sa SafeEmitterArg Releaser
420  * @sa emitter.h
421  * @sa Callback namespace
422  *
423  * Callback::FunctorArg objects may be connected to Emitter classes,
424  * and will be executed when EmitterArg::emit() or
425  * EmitterArg::operator()() are called.
426  *
427  * One version of the connect() method takes a Releaser object as an
428  * argument. Such a Releaser object should be a public member of any
429  * target class which wants functors representing any of its methods
430  * to be disconnected automatically from the EmitterArg object when
431  * the target class object is destroyed.
432  *
433  * A connection may be explicitly disconnected by calling the
434  * disconnect() method, and may also be temporarily blocked and
435  * subsequently unblocked with the block() and unblock() methods.
436  *
437  * The template types are the types of the unbound arguments, if any.
438  * EmitterArg<> is typedef'ed to Emitter.
439  *
440  * @b Usage
441  *
442  * For a class my_obj of type MyClass, with a method void
443  * MyClass::my_method(int, int, const char*), usage for a fully bound functor
444  * and emitter would be:
445  *
446  * @code
447  * using namespace Cgu;
448  * int arg1 = 1, arg2 = 5;
449  * Emitter e;
450  * e.connect(Callback::make(my_obj, &MyClass::my_method, arg1, arg2, "Hello\n"));
451  * e();
452  * @endcode
453  *
454  * Or for a partially bound functor and emitter:
455  *
456  * @code
457  * using namespace Cgu;
458  * int arg1 = 1, arg2 = 5;
459  * EmitterArg<int, const char*> e;
460  * e.connect(Callback::make(my_obj, &MyClass::my_method, arg1));
461  * e(arg2, "Hello\n");
462  * @endcode
463  *
464  * For further background, including about thread-safety and exception
465  * safety and other matters, read this: emitter.h, or for more
466  * information about bound and unbound arguments, read this:
467  * Cgu::Callback.
468  */
469 
470 template <class... FreeArgs>
471 class EmitterArg {
472 
473 #ifndef DOXYGEN_PARSING
474  // f1 is the functor we execute when we emit()
475  // f2 is the functor we execute in our destructor if we are destroyed
476  // before the remote object is
477  struct ListItem {
478  Callback::FunctorArg<FreeArgs...> f1;
480  bool blocked;
482  f1(f1_), f2(f2_), blocked(false) {}
483  };
484 #endif
485 
486  std::list<ListItem> emission_list;
487 
488  // only Releaser objects can access this
489  void tracking_disconnect(const Callback::FunctorArg<FreeArgs...>&);
490 
491 public:
492  friend class Releaser;
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 operator()(typename Cgu::Param<FreeArgs>::ParamType... args) const {emit(args...);}
505 
506 /**
507  * This will execute the connected functors.
508  * @param args The unbound arguments to be passed to the referenced
509  * function or class method, if any.
510  * @exception std::bad_alloc The method might throw std::bad_alloc if
511  * memory is exhausted and the system throws in that case. In
512  * addition, it will throw if the functions or class methods
513  * referenced by the functors throw (or if the copy constructor of a
514  * free or bound argument throws and it is not a reference argument).
515  */
516  void emit(typename Cgu::Param<FreeArgs>::ParamType... args) const;
517 
518 /**
519  * This will execute the connected functors, but it also reports
520  * whether in fact there were any connected functors to execute. (It
521  * is not necessary to use this function just because it is not known
522  * whether a functor is connected - if the standard emit() function is
523  * called when no functor is connected, nothing will happen. The
524  * feature of this method is that it will report the outcome.)
525  * @param args The unbound arguments to be passed to the connected
526  * functions or class methods, if any.
527  * @return Returns false if there were no functors to execute, or true
528  * if functors have been executed.
529  * @exception std::bad_alloc The method might throw std::bad_alloc if
530  * memory is exhausted and the system throws in that case. In
531  * addition, it will throw if the functions or class methods
532  * referenced by the functors throw (or if the copy constructor of a
533  * free or bound argument throws and it is not a reference argument).
534  */
535  bool test_emit(typename Cgu::Param<FreeArgs>::ParamType... args) const;
536 
537 /**
538  * Connects a functor.
539  * @param f The functor to connect.
540  * @return The functor connected.
541  * @exception std::bad_alloc The method might throw std::bad_alloc if
542  * memory is exhausted and the system throws in that case.
543  */
545 
546 /**
547  * Connects a functor.
548  * @param f The functor to connect.
549  * @param r A Releaser object for automatic disconnection of the
550  * functor if the object whose method it represents is destroyed.
551  * @return The functor connected.
552  * @exception std::bad_alloc The method might throw std::bad_alloc if
553  * memory is exhausted and the system throws in that case.
554  */
556 
557 /**
558  * Disconnects a functor previously connected. This does not throw
559  * provided that the destructors of any bound arguments do not throw
560  * (as they should not do), and assuming that merely iterating through
561  * a list does not throw (as it would not on any sane implementation).
562  * @param f The functor to disconnect.
563  * @note If the same functor has been connected more than once to the
564  * same EmitterArg object, this call will disconnect all of them.
565  */
567 
568 /**
569  * Blocks a connected functor from executing when emit() or
570  * operator()() is called until unblock() is called. This method does
571  * not throw (assuming that merely iterating through a list does not
572  * throw, as it would not on any sane implementation).
573  * @param f The functor to block.
574  * @note If the same functor has been connected more than once to the
575  * same EmitterArg object, this call will block all of them.
576  */
578 
579 /**
580  * Unblocks a previously blocked functor. This method does not throw
581  * (assuming that merely iterating through a list does not throw, as
582  * it would not on any sane implementation).
583  * @param f The functor to unblock.
584  * @note If the same functor has been connected more than once to the
585  * same EmitterArg object, this call will unblock all of them.
586  */
588 
589 /**
590  * @exception std::bad_alloc The constructor might throw
591  * std::bad_alloc if memory is exhausted and the system throws in that
592  * case.
593  */
594  EmitterArg() = default;
595 
596 /**
597  * This class cannot be copied. The copy constructor is deleted.
598  */
599  EmitterArg(const EmitterArg&) = delete;
600 
601 /**
602  * This class cannot be copied. The assignment operator is deleted.
603  */
604  EmitterArg& operator=(const EmitterArg&) = delete;
605 
606 /**
607  * The destructor does not throw provided that the destructors of any
608  * bound arguments do not throw (as they should not do), and assuming
609  * that merely iterating through a list does not throw (as it would
610  * not on any sane implementation).
611  */
612  ~EmitterArg();
613 
614 /* Only has effect if --with-glib-memory-slices-compat or
615  * --with-glib-memory-slices-no-compat option picked */
617 };
618 
619 template <class... FreeArgs>
621 
622  // gcc-4.4 and 4.5 don't support this:
623  /*
624  for(const ListItem& l: emission_list) {l.f2();}
625  */
626  // gcc-4.4 doesn't support this;
627  /*
628  std::for_each(emission_list.begin(), emission_list.end(),
629  [](const ListItem& l){(l.f2)();});
630  */
631  // So do it the old way:
632  struct DisconnectReleaserItem {
633  static void exec(const ListItem& l) {(l.f2)();}
634  };
635  std::for_each(emission_list.begin(), emission_list.end(),
636  DisconnectReleaserItem::exec);
637 }
638 
639 template <class... FreeArgs>
641 
642  // create a local copy of emission_list, to enable a connected
643  // function (i) to delete the EmitterArg<> object to which it is
644  // connected, even if there are other functors still to execute in
645  // the same emission (which will execute normally provided they do
646  // not try to call any of the emitter's functions), (ii) to call
647  // 'delete this' nothwithstanding that the connected function is
648  // protected by a Releaser object (assuming all the other restraints
649  // on calling 'delete this' are met), provided that no other access
650  // would be made to the deleted object in a function call connected
651  // to the same emitter which is due to execute subsequently in the
652  // same emission, and (iii) to disconnect itself from the
653  // EmitterArg object. This design approach has a trade-off: if a
654  // connected function tries to block, unblock or disconnect another
655  // function connected to the same EmitterArg<> object which is due
656  // to execute subsequently in the same emission (or to block,
657  // unblock or disconnect itself when it is due to execute again
658  // subsequently in the same emission), the attempted block, unblock
659  // or disconnection will not have any effect on that emission (it
660  // will only have effect on a subsequent emission). In addition, a
661  // connected function may not destroy an object whose non-static
662  // method is connected to the same emitter and which would execute
663  // subsequently in the same emission, even if that object is
664  // protected by a Releaser object (the non-static method will
665  // unsuccessfully attempt to execute notwithstanding the destruction
666  // of the object it would be operating on).
667 
668  // we can't use uniform initialisation here as it would be
669  // construed as invoking an initialiser list with a list item,
670  // rather than passing an already formed list
671  std::list<ListItem> local_list = emission_list;
672 
673 /*
674  gcc-4.4 doesn't support lambdas, gcc-4.5 doesn't like lambda
675  captures which comprise variadic arguments, and neither support
676  range-based for, so iterate by hand
677 */
678  typename std::list<ListItem>::const_iterator iter;
679  for (iter = local_list.begin(); iter != local_list.end(); ++iter) {
680  if (!iter->blocked) iter->f1(args...);
681  }
682 }
683 
684 template <class... FreeArgs>
686  if (emission_list.empty()) return false;
687  emit(args...);
688  return true;
689 }
690 
691 template <class... FreeArgs>
693  emission_list.push_back(ListItem{f1, Callback::Functor()});
694  return f1;
695 }
696 
697 template <class... FreeArgs>
699  // In this method:
700  // f1 is the functor we execute when we emit()
701  // f2 is the functor we execute in our destructor if we are destroyed before the
702  // remote object is
703  // f3 is the functor the remote object executes in its Releaser if it is destroyed
704  // before we are, or if Releaser::operator=() is called
705 
707  Callback::Functor f2{Callback::make_ref(r, &Releaser::remove, f3)};
708  r.add(f3);
709  try {
710  emission_list.push_back(ListItem{f1, f2});
711  }
712  catch (...) {
713  r.remove(f3);
714  throw;
715  }
716  return f1;
717 }
718 
719 template <class... FreeArgs>
721  // in theory, we could have connected the same functor object
722  // more than once, so cater for that
723  auto iter = emission_list.begin();
724  for (;;) {
725  // gcc-4.4 doesn't support lambdas:
726  /*
727  iter = std::find_if(iter, emission_list.end(),
728  [&arg](const ListItem& p) -> bool {return p.f1 == arg;});
729  */
730  // so use a local struct and std::bind:
731  struct Pred {
732  static bool pred(const ListItem& p, const Callback::FunctorArg<FreeArgs...>& f) {
733  return (p.f1 == f);
734  }
735  };
736  iter = std::find_if(iter, emission_list.end(),
737  std::bind(Pred::pred, std::placeholders::_1, std::ref(arg)));
738  if (iter != emission_list.end()) {
739  // remove ourselves from the remote Releaser object
740  (iter->f2)();
741 
742  // remove this item from emission_list
743  iter = emission_list.erase(iter);
744  }
745  else break;
746  }
747 }
748 
749 // tracking disconnect() is the same as disconnect(), except that we do not
750 // execute f2 as the remote Releaser object will destroy its own functors
751 // in that case
752 template <class... FreeArgs>
754  auto iter = emission_list.begin();
755  for (;;) {
756  // gcc-4.4 doesn't support lambdas:
757  /*
758  iter = std::find_if(iter, emission_list.end(),
759  [&arg](const ListItem& p) -> bool {return p.f1 == arg;});
760  */
761  // so use a local struct and std::bind:
762  struct Pred {
763  static bool pred(const ListItem& p, const Callback::FunctorArg<FreeArgs...>& f) {
764  return (p.f1 == f);
765  }
766  };
767  iter = std::find_if(iter, emission_list.end(),
768  std::bind(Pred::pred, std::placeholders::_1, std::ref(arg)));
769  if (iter != emission_list.end()) {
770  // remove this item from emission_list
771  iter = emission_list.erase(iter);
772  }
773  else break;
774  }
775 }
776 
777 template <class... FreeArgs>
779  // in theory, we could have connected the same functor object
780  // more than once, so cater for that
781  auto iter = emission_list.begin();
782  for (;;) {
783  // gcc-4.4 doesn't support lambdas:
784  /*
785  iter = std::find_if(iter, emission_list.end(),
786  [&arg](const ListItem& p) -> bool {return p.f1 == arg;});
787  */
788  // so use a local struct and std::bind:
789  struct Pred {
790  static bool pred(const ListItem& p, const Callback::FunctorArg<FreeArgs...>& f) {
791  return (p.f1 == f);
792  }
793  };
794  iter = std::find_if(iter, emission_list.end(),
795  std::bind(Pred::pred, std::placeholders::_1, std::ref(arg)));
796  if (iter != emission_list.end()) {
797  iter->blocked = true;
798  ++iter;
799  }
800  else break;
801  }
802 }
803 
804 template <class... FreeArgs>
806  // in theory, we could have connected the same functor object
807  // more than once, so cater for that
808  auto iter = emission_list.begin();
809  for (;;) {
810  // gcc-4.4 doesn't support lambdas:
811  /*
812  iter = std::find_if(iter, emission_list.end(),
813  [&arg](const ListItem& p) -> bool {return p.f1 == arg;});
814  */
815  // so use a local struct and std::bind:
816  struct Pred {
817  static bool pred(const ListItem& p, const Callback::FunctorArg<FreeArgs...>& f) {
818  return (p.f1 == f);
819  }
820  };
821  iter = std::find_if(iter, emission_list.end(),
822  std::bind(Pred::pred, std::placeholders::_1, std::ref(arg)));
823  if (iter != emission_list.end()) {
824  iter->blocked = false;
825  ++iter;
826  }
827  else break;
828  }
829 }
830 
831 /**
832  * @class SafeEmitterArg emitter.h c++-gtk-utils/emitter.h
833  * @brief A thread-safe class to execute callbacks connected to it,
834  * with provision for automatic disconnection.
835  * @sa EmitterArg Releaser
836  * @sa emitter.h
837  * @sa Callback namespace
838  *
839  * This is a thread-safe version of the EmitterArg class.
840  * Callback::SafeFunctorArg objects may be connected to SafeEmitter
841  * classes, and will be executed when SafeEmitterArg::emit() or
842  * SafeEmitterArg::operator()() are called.
843  *
844  * One version of the connect() method takes a Releaser object as an
845  * argument. Such a Releaser object should be a public member of any
846  * target class which wants functors representing any of its methods
847  * to be disconnected automatically from the SafeEmitterArg object
848  * when the target class object is destroyed.
849  *
850  * A connection may be explicitly disconnected by calling the
851  * disconnect() method, and may also be temporarily blocked and
852  * subsequently unblocked with the block() and unblock() methods.
853  *
854  * The template types are the types of the unbound arguments, if any.
855  * SafeEmitterArg<> is typedef'ed to SafeEmitter.
856  *
857  * @b Usage
858  *
859  * For a class my_obj of type MyClass, with a method void
860  * MyClass::my_method(int, int, const char*), usage for a fully bound
861  * functor and emitter would be:
862  *
863  * @code
864  * using namespace Cgu;
865  * int arg1 = 1, arg2 = 5;
866  * SafeEmitter se;
867  * se.connect(Callback::make(my_obj, &MyClass::my_method, arg1, arg2, "Hello\n"));
868  * se();
869  * @endcode
870  *
871  * Or for a partially bound functor and emitter:
872  *
873  * @code
874  * using namespace Cgu;
875  * int arg1 = 1, arg2 = 5;
876  * SafeEmitterArg<int, const char*> se;
877  * se.connect(Callback::make(my_obj, &MyClass::my_method, arg1));
878  * se(arg2, "Hello\n");
879  * @endcode
880  *
881  * For further background, including about thread-safety and exception
882  * safety and other matters, read this: emitter.h, or for more
883  * information about bound and unbound arguments, read this:
884  * Cgu::Callback.
885  */
886 
887 template <class... FreeArgs>
889 
890 #ifndef DOXYGEN_PARSING
891  // f1 is the functor we execute when we emit()
892  // f2 is the functor we execute in our destructor if we are destroyed
893  // before the remote object is
894  struct ListItem {
895  Callback::SafeFunctorArg<FreeArgs...> f1;
897  bool blocked;
899  f1(f1_), f2(f2_), blocked(false) {}
900  };
901 #endif
902 
903  std::list<ListItem> emission_list;
904  mutable Thread::Mutex mutex; // make this mutable so we can lock/unlock in const methods
905 
906  // only Releaser objects can access this
907  void tracking_disconnect(const Callback::SafeFunctorArg<FreeArgs...>&);
908 
909 public:
910  friend class Releaser;
911 
912 /**
913  * This will execute the connected functors. It is thread safe if the
914  * functions or class methods referenced by the connected functors are
915  * thread safe.
916  * @param args The unbound arguments to be passed to the referenced
917  * function or class method, if any.
918  * @exception std::bad_alloc The method might throw std::bad_alloc if
919  * memory is exhausted and the system throws in that case. In
920  * addition, it will throw if the functions or class methods
921  * referenced by the functors throw (or if the copy constructor of a
922  * free or bound argument throws and it is not a reference argument).
923  */
924  void operator()(typename Cgu::Param<FreeArgs>::ParamType... args) const {emit(args...);}
925 
926 /**
927  * This will execute the connected functors. It is thread safe if the
928  * functions or class methods referenced by the connected functors are
929  * thread safe.
930  * @param args The unbound arguments to be passed to the referenced
931  * function or class method, if any.
932  * @exception std::bad_alloc The method might throw std::bad_alloc if
933  * memory is exhausted and the system throws in that case. In
934  * addition, it will throw if the functions or class methods
935  * referenced by the functors throw (or if the copy constructor of a
936  * free or bound argument throws and it is not a reference argument).
937  */
938  void emit(typename Cgu::Param<FreeArgs>::ParamType... args) const;
939 
940 /**
941  * This will execute the connected functors, but it also reports
942  * whether in fact there were any connected functors to execute. It
943  * is thread safe if the functions or class methods referenced by the
944  * connected functors are thread safe. (It is not necessary to use
945  * this function just because it is not known whether a functor is
946  * connected - if the standard emit() function is called when no
947  * functor is connected, nothing will happen. The feature of this
948  * method is that it will report the outcome.)
949  * @param args The unbound arguments to be passed to the referenced
950  * function or class method, if any.
951  * @return Returns false if there were no functors to execute, or true
952  * if functors have been executed.
953  * @exception std::bad_alloc The method might throw std::bad_alloc if
954  * memory is exhausted and the system throws in that case. In
955  * addition, it will throw if the functions or class methods
956  * referenced by the functors throw (or if the copy constructor of a
957  * free or bound argument throws and it is not a reference argument).
958  */
959  bool test_emit(typename Cgu::Param<FreeArgs>::ParamType... args) const;
960 
961 /**
962  * Connects a functor. It is thread safe.
963  * @param f The functor to connect.
964  * @return The functor connected.
965  * @exception std::bad_alloc The method might throw std::bad_alloc if
966  * memory is exhausted and the system throws in that case.
967  */
969 
970 /**
971  * Connects a functor. It is thread safe.
972  * @param f The functor to connect.
973  * @param r A Releaser object for automatic disconnection of the
974  * functor if the object whose method it represents is destroyed.
975  * @return The functor connected.
976  * @exception std::bad_alloc The method might throw std::bad_alloc if
977  * memory is exhausted and the system throws in that case.
978  */
980 
981 /**
982  * Disconnects a functor previously connected. This does not throw
983  * provided that the destructors of any bound arguments do not throw
984  * (as they should not do), and assuming that merely iterating through
985  * a list does not throw (as it would not on any sane implementation).
986  * It is thread safe.
987  * @param f The functor to disconnect.
988  * @note If the same functor has been connected more than once to the
989  * same SafeEmitterArg object, this call will disconnect all of them.
990  */
992 
993 /**
994  * Blocks a connected functor from executing when emit() or
995  * operator()() is called until unblock() is called. This method does
996  * not throw (assuming that merely iterating through a list does not
997  * throw, as it would not on any sane implementation). It is thread
998  * safe.
999  * @param f The functor to block.
1000  * @note If the same functor has been connected more than once to the
1001  * same SafeEmitterArg object, this call will block all of them.
1002  */
1004 
1005 /**
1006  * Unblocks a previously blocked functor. This method does not throw
1007  * (assuming that merely iterating through a list does not throw, as
1008  * it would not on any sane implementation). It is thread safe.
1009  * @param f The functor to unblock.
1010  * @note If the same functor has been connected more than once to the
1011  * same SafeEmitterArg object, this call will unblock all of them.
1012  */
1014 
1015 /**
1016  * @exception std::bad_alloc The constructor might throw
1017  * std::bad_alloc if memory is exhausted and the system throws in that
1018  * case.
1019  * @exception Thread::MutexError The constructor might throw
1020  * Thread::MutexError if initialisation of the contained mutex fails.
1021  * (It is often not worth checking for this, as it means either memory
1022  * is exhausted or pthread has run out of other resources to create
1023  * new mutexes.)
1024  */
1025  SafeEmitterArg() = default;
1026 
1027 /**
1028  * This class cannot be copied. The copy constructor is deleted.
1029  */
1030  SafeEmitterArg(const SafeEmitterArg&) = delete;
1031 
1032 /**
1033  * This class cannot be copied. The assignment operator is deleted.
1034  */
1035  SafeEmitterArg& operator=(const SafeEmitterArg&) = delete;
1036 
1037 /**
1038  * The destructor does not throw provided that the destructors of any
1039  * bound arguments do not throw (as they should not do), and assuming
1040  * that merely iterating through a list does not throw (as it would
1041  * not on any sane implementation). It is thread-safe as regards the
1042  * dropping of any connected functors and of any relevant Releaser
1043  * objects.
1044  */
1045  ~SafeEmitterArg();
1046 
1047 /* Only has effect if --with-glib-memory-slices-compat or
1048  * --with-glib-memory-slices-no-compat option picked */
1050 };
1051 
1052 template <class... FreeArgs>
1054 
1055  // go through emission_list() item by item, popping off the front and erasing
1056  // as we go in case Releaser::try_remove() fails to acquire the lock on one
1057  // of the iterations
1058  Thread::Mutex::Lock lock{mutex};
1059  while (!emission_list.empty()) {
1060  auto iter = emission_list.begin();
1061  int result = 0; // f2 might be a no-op
1062  // remove ourselves from the remote Releaser object
1063  (iter->f2)(&result);
1064  if (!result) { // we got the Releaser mutex lock or no-op
1065  // now remove this item from emission_list
1066  emission_list.erase(iter);
1067  }
1068  else {
1069  mutex.unlock();
1070  // spin nicely
1071 #ifdef CGU_USE_SCHED_YIELD
1072  sched_yield();
1073 #else
1074  usleep(10);
1075 #endif
1076  mutex.lock();
1077  }
1078  }
1079 }
1080 
1081 template <class... FreeArgs>
1083 
1084  // create a local copy of emission_list, to enable a connected
1085  // function (i) to delete the EmitterArg<> object to which it is
1086  // connected, even if there are other functors still to execute in
1087  // the same emission (which will execute normally provided they do
1088  // not try to call any of the emitter's functions), (ii) to call
1089  // 'delete this' nothwithstanding that the connected function is
1090  // protected by a Releaser object (assuming all the other restraints
1091  // on calling 'delete this' are met), provided that no other access
1092  // would be made to the deleted object in a function call connected
1093  // to the same emitter which is due to execute subsequently in the
1094  // same emission, and (iii) to disconnect itself from the
1095  // EmitterArg<> object. This design approach has a trade-off: if a
1096  // connected function tries to block, unblock or disconnect another
1097  // function connected to the same EmitterArg<> object which is due
1098  // to execute subsequently in the same emission (or to block,
1099  // unblock or disconnect itself when it is due to execute again
1100  // subsequently in the same emission), the attempted block, unblock
1101  // or disconnection will not have any effect on that emission (it
1102  // will only have effect on a subsequent emission). In addition, a
1103  // connected function may not destroy an object whose non-static
1104  // method is connected to the same emitter and which would execute
1105  // subsequently in the same emission, even if that object is
1106  // protected by a Releaser object (the non-static method will
1107  // unsuccessfully attempt to execute notwithstanding the destruction
1108  // of the object it would be operating on).
1109 
1110  // SafeFunctorArg usage has the additional point that while an
1111  // emission is in course, another thread should not try to do any of
1112  // those things, or the same outcome will result. Another thread
1113  // should leave alone objects connected to a SafeEmitterArg<> object
1114  // from the time of operator()() or emit() beginning to the time of
1115  // it ending, and not try to interfere.
1116 
1117  // a side effect of having a local list is that, as required, we
1118  // will not be holding our mutex when executing the functors it
1119  // contains. It is OK having the functors in two different lists
1120  // which are potentially (when our mutex is released) in two
1121  // different threads, because the functors hold their
1122  // Callback::Callback objects by SharedLockPtr so their reference
1123  // count is protected (they are SafeFunctorArg<> functors).
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  Thread::Mutex::Lock lock{mutex};
1167  emission_list.push_back(ListItem{f1, Callback::SafeFunctorArg<int*>()});
1168  return f1;
1169 }
1170 
1171 template <class... FreeArgs>
1173  // In this method:
1174  // f1 is the functor we execute when we emit()
1175  // f2 is the functor we execute in our destructor if we are destroyed before the
1176  // remote object is
1177  // f3 is the functor the remote object executes in its Releaser if it is destroyed
1178  // before we are, or if Releaser::operator=() is called
1179 
1181  Callback::SafeFunctorArg<int*> f2{Callback::make_ref(r, &Releaser::try_remove, f3)};
1182  // we can't call Releaser::add() when holding our mutex or we will
1183  // get out of order locking, as Releaser's mutex is acquired in that
1184  // method, and we don't need to do so
1185  r.add(f3);
1186  Thread::Mutex::Lock lock{mutex};
1187  try {
1188  emission_list.push_back(ListItem{f1, f2});
1189  }
1190  catch (...) {
1191  mutex.unlock();
1192  r.remove(f3);
1193  mutex.lock();
1194  throw;
1195  }
1196  return f1;
1197 }
1198 
1199 template <class... FreeArgs>
1201  // in theory, we could have connected the same functor object more than
1202  // once, so cater for that as well as Releaser::try_remove() failing
1203  Thread::Mutex::Lock lock{mutex};
1204  auto iter = emission_list.begin();
1205  for(;;) {
1206  /*
1207  // gcc-4.4 doesn't support lambdas:
1208  iter = std::find_if(iter, emission_list.end(),
1209  [&arg](const ListItem& p) -> bool {return p.f1 == arg;});
1210  */
1211  // so use a local struct and std::bind:
1212  struct Pred {
1213  static bool pred(const ListItem& p, const Callback::SafeFunctorArg<FreeArgs...>& f) {
1214  return (p.f1 == f);
1215  }
1216  };
1217  iter = std::find_if(iter, emission_list.end(),
1218  std::bind(Pred::pred, std::placeholders::_1, std::ref(arg)));
1219  if (iter != emission_list.end()) {
1220  int result = 0; // f2 might be a no-op
1221  // remove ourselves from the remote Releaser object
1222  (iter->f2)(&result);
1223  if (!result) { // we got the Releaser mutex lock or no-op
1224  // now remove this item from emission_list
1225  iter = emission_list.erase(iter);
1226  }
1227  else {
1228  mutex.unlock();
1229  // spin nicely
1230 #ifdef CGU_USE_SCHED_YIELD
1231  sched_yield();
1232 #else
1233  usleep(10);
1234 #endif
1235  mutex.lock();
1236  // start again at the beginning - we have released the mutex
1237  // so our iterator may have become invalid
1238  iter = emission_list.begin();
1239  }
1240  }
1241  else break;
1242  }
1243 }
1244 
1245 // tracking disconnect() is the same as disconnect(), except that we do not
1246 // execute f2 as the remote Releaser object will destroy its own functors
1247 // in that case
1248 template <class... FreeArgs>
1250  Thread::Mutex::Lock lock{mutex};
1251  auto iter = emission_list.begin();
1252  for (;;) {
1253  // gcc-4.4 doesn't support lambdas:
1254  /*
1255  iter = std::find_if(iter, emission_list.end(),
1256  [&arg](const ListItem& p) -> bool {return p.f1 == arg;});
1257  */
1258  // so use a local struct and std::bind:
1259  struct Pred {
1260  static bool pred(const ListItem& p, const Callback::SafeFunctorArg<FreeArgs...>& f) {
1261  return (p.f1 == f);
1262  }
1263  };
1264  iter = std::find_if(iter, emission_list.end(),
1265  std::bind(Pred::pred, std::placeholders::_1, std::ref(arg)));
1266  if (iter != emission_list.end()) {
1267  // remove this item from emission_list
1268  iter = emission_list.erase(iter);
1269  }
1270  else break;
1271  }
1272 }
1273 
1274 template <class... FreeArgs>
1276  // in theory, we could have connected the same functor object
1277  // more than once, so cater for that
1278  Thread::Mutex::Lock lock{mutex};
1279  auto iter = emission_list.begin();
1280  for (;;) {
1281  // gcc-4.4 doesn't support lambdas:
1282  /*
1283  iter = std::find_if(iter, emission_list.end(),
1284  [&arg](const ListItem& p) -> bool {return p.f1 == arg;});
1285  */
1286  // so use a local struct and std::bind:
1287  struct Pred {
1288  static bool pred(const ListItem& p, const Callback::SafeFunctorArg<FreeArgs...>& f) {
1289  return (p.f1 == f);
1290  }
1291  };
1292  iter = std::find_if(iter, emission_list.end(),
1293  std::bind(Pred::pred, std::placeholders::_1, std::ref(arg)));
1294  if (iter != emission_list.end()) {
1295  iter->blocked = true;
1296  ++iter;
1297  }
1298  else break;
1299  }
1300 }
1301 
1302 template <class... FreeArgs>
1304  // in theory, we could have connected the same functor object
1305  // more than once, so cater for that
1306  Thread::Mutex::Lock lock{mutex};
1307  auto iter = emission_list.begin();
1308  for (;;) {
1309  // gcc-4.4 doesn't support lambdas:
1310  /*
1311  iter = std::find_if(iter, emission_list.end(),
1312  [&arg](const ListItem& p) -> bool {return p.f1 == arg;});
1313  */
1314  // so use a local struct and std::bind:
1315  struct Pred {
1316  static bool pred(const ListItem& p, const Callback::SafeFunctorArg<FreeArgs...>& f) {
1317  return (p.f1 == f);
1318  }
1319  };
1320  iter = std::find_if(iter, emission_list.end(),
1321  std::bind(Pred::pred, std::placeholders::_1, std::ref(arg)));
1322  if (iter != emission_list.end()) {
1323  iter->blocked = false;
1324  ++iter;
1325  }
1326  else break;
1327  }
1328 }
1329 
1330 } // namespace Cgu
1331 
1332 #endif // EMITTER_H