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