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<void>.
53  * The generalised EmitterArg<T> type contains
54  * Callback::FunctorArg<T> objects (type T being the unbound
55  * argument of a Callback::CallbackArg<T> callback or the type
56  * container of unbound types - see Cgu::Callback for further
57  * details, and "Usage" below for examples.) The Emitter type holds
58  * Callback::Functor (namely Callback::FunctorArg<void>) 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  * For an object my_obj of class type MyClass, with a method void
207  * MyClass::my_method(int, const char*), usage for a fully bound
208  * functor and emitter would be:
209  *
210  * @code
211  * using namespace Cgu;
212  * int arg = 1;
213  * Emitter e;
214  * e.connect(Callback::make(my_obj, &MyClass::my_method, arg, "Hello\n"));
215  * e();
216  *
217  * SafeEmitter se;
218  * se.connect(Callback::make(my_obj, &MyClass::my_method, arg, "Hello\n"));
219  * se();
220  * @endcode
221  *
222  * Or for a partially bound functor and emitter:
223  *
224  * @code
225  * using namespace Cgu;
226  * int arg = 1;
227  * EmitterArg<const char*> e;
228  * e.connect(Callback::make(my_obj, &MyClass::my_method, arg));
229  * e("Hello\n");
230  *
231  * SafeEmitterArg<const char*> se;
232  * se.connect(Callback::make(my_obj, &MyClass::my_method, arg));
233  * se("Hello\n");
234  * @endcode
235  *
236  * To provide for two or three unbound arguments, from version 1.2.10
237  * of the library the Cgu::TypeTuple struct is used (this struct has
238  * no members and is never instantiated, so it does not impose any
239  * overhead: see @ref TypeTuple for further information). As in the
240  * case of a single unbound argument, if there are bound arguments
241  * these multiple unbound arguments must be the last (trailing)
242  * arguments of the function to be called. For a class object my_obj
243  * of type MyClass, with a method void MyClass::my_method2(int, int,
244  * int, const char*), usage with two unbound arguments would be:
245  *
246  * @code
247  * int arg1 = 1, arg2 = 2, arg3 = 3;
248  * Cgu::EmitterArg<Cgu::TypeTuple<int, const char*> > e;
249  * e.connect(Cgu::Callback::make(my_obj, &MyClass::my_method2, arg1, arg2));
250  * e(arg3, "Hello\n");
251  * @endcode
252  *
253  * and for three unbound arguments:
254  *
255  * @code
256  * int arg1 = 1, arg2 = 2, arg3 = 3;
257  * Cgu::EmitterArg<Cgu::TypeTuple<int, int, const char*> > e;
258  * e.connect(Cgu::Callback::make(my_obj, &MyClass::my_method2, arg1));
259  * e(arg2, arg3, "Hello\n");
260  * @endcode
261  *
262  * EmitterArg classes do not provide for a return value. If a
263  * result is wanted, users should pass an unbound argument by
264  * reference or pointer (or pointer to pointer).
265  *
266  * Although only two bound and three unbound arguments are provided
267  * for, as any of those arguments can be a struct, any number of
268  * arguments can be passed as members of a struct (or, in C++11, a
269  * std::tuple).
270  *
271  * Exception safety
272  * ----------------
273  *
274  * Apart from the emit()/operator()() and connect() methods, nothing
275  * done to an EmitterArg/SafeEmitterArg object should cause an
276  * exception to be thrown. This is because other methods only iterate
277  * through a std::list object using std::for_each(), std::find() or by
278  * hand, and the only things done by std::for_each() or after a
279  * std::find() or iteration is to remove a functor from the list
280  * (copying a functor and comparing functors never throw, nor does
281  * destroying a functor provided the destructors of any bound argument
282  * type do not throw). Thus, an EmitterArg/SafeEmitterArg and
283  * Releaser object should never get into an inconsistent state.
284  *
285  * The connect() method could throw a std::bad_alloc exception, either
286  * on creating new functors or on pushing the functors onto the list.
287  * However, were it to do so, the method has strong exception safety
288  * (assuming merely iterating over a list does not throw, as it should
289  * not).
290  *
291  * The emit()/operator()() methods could throw std::bad_alloc, and so
292  * far as that is concerned emission of all the connected functions
293  * will either all succeed or all fail. In addition, the connected
294  * functions referenced by the functors held by the emitter might
295  * throw when executed. emit()/operator()() do not attempt to catch
296  * these exceptions as there is nothing they could do with them. This
297  * means that although a throwing connected function will not leave
298  * the EmitterArg/SafeEmitterArg object in an inconsistent state, any
299  * other connected functions due to execute subsequently on that same
300  * emission will not execute. If that is important in any particular
301  * case, the user must incorporate logic in the connected functions to
302  * cater for an exception causing only part execution, or must connect
303  * only one function to any one signal and "chain" emissions by hand
304  * so as to do the right thing.
305  */
306 
307 /*
308  Mutex locking heirarchy:
309 
310  Some out-of-order locking must take place because of the
311  relationship between the Releaser and SafeEmitterArg<> classes. The
312  mutex of Releaser is given the higher priority. This means that a
313  plain EmitterArg<> object will not take any hit from the fact that
314  Releaser is also useable with SafeEmitterArg<> objects.
315 
316  One consequence is that to avoid deadlocks, it is the
317  SafeEmitterArg<> functions which must yield when a deadlock would
318  otherwise arise. Yielding could occur in
319  SafeEmitterArg<>::~SafeEmitterArg() and
320  SafeEmitterArg<>::disconnect().
321 */
322 
323 #ifdef CGU_USE_SCHED_YIELD
324 #include <sched.h>
325 #else
326 #include <unistd.h>
327 #endif
328 
329 #include <list>
330 #include <algorithm>
331 #include <functional>
332 
333 #include <c++-gtk-utils/callback.h>
334 #include <c++-gtk-utils/param.h>
335 #include <c++-gtk-utils/mutex.h>
337 
338 namespace Cgu {
339 
340 /* The four basic emitter types */
341 
342 template <class FreeArg> class EmitterArg;
343 template <class FreeArg> class SafeEmitterArg;
344 typedef EmitterArg<void> Emitter;
346 
347 /**
348  * @class Releaser emitter.h c++-gtk-utils/emitter.h
349  * @brief A class used for tracking EmitterArg and SafeEmitterArg
350  * connections.
351  * @sa EmitterArg SafeEmitterArg
352  * @sa emitter.h
353  * @sa Callback namespace
354  *
355  * This class provides tracking of EmitterArg and SafeEmitterArg
356  * connections. It should be a public member of any target class
357  * which wants functors representing any of its methods to be
358  * disconnected automatically from an EmitterArg or SafeEmitterArg
359  * object when the target class object is destroyed, and is passed as
360  * one of the arguments to the connect() method of EmitterArg or
361  * SafeEmitterArg.
362  *
363  * All its methods are thread-safe.
364  *
365  * For further background, read this: emitter.h
366  */
367 
368 class Releaser {
369 
370  // TODO: In the 2.0 series we use std::unordered_set instead of
371  // std::list in Releaser. At a suitable binary break I think it
372  // would be useful to convert to std::set in this 1.2 series. We
373  // can't do that for EmitterArg/SafeEmitterArg objects, as they need
374  // to execute connected functors in the order in which they were
375  // connected.
376  std::list<Callback::SafeFunctor> disconnect_list;
377  Thread::Mutex mutex;
378 
379  // only an EmitterArg or SafeEmitterArg object can access add(), remove and try_remove()
380  // TODO On an ABI break, change remove() and try_remove() to take a
381  // const Callback::SafeFunctor& argument: we can do this now that we
382  // have Callback::make_ref() available from version 1.2.13.
383  void add(const Callback::SafeFunctor&);
384  void remove(Callback::SafeFunctor);
385  void try_remove(Callback::SafeFunctor, int*);
386 public:
387  template <class T> friend class EmitterArg;
388  template <class T> friend class SafeEmitterArg;
389 
390  // operator=() and the copy constructor should copy nothing from the
391  // assignor, because disconnect_list should be empty in the
392  // sssignee, as any class containing us does not acquire as assignee
393  // any emitter functors representing any of its methods
394 
395 /**
396  * See notes on @ref AssignmentAnchor "assignment" to see how this
397  * operates. This does not throw provided that the destructors of any
398  * bound arguments of a functor managed by this Releaser object prior
399  * to assignment do not throw (as they should not do), and assuming
400  * that merely iterating through a list does not throw (as it would
401  * not on any sane implementation).
402  * @param r The assignee.
403  */
404  Releaser& operator=(const Releaser& r);
405 
406 /**
407  * This does not copy anything from the Releaser object passed as an
408  * argument - see the notes on @ref AssignmentAnchor "assignment" for
409  * an explanation of why. This does not throw.
410  * @param r A Releaser object.
411  * @exception std::bad_alloc This constructor might throw
412  * std::bad_alloc if memory is exhausted and the system throws in that
413  * case.
414  * @exception Thread::MutexError This constructor might throw
415  * Thread::MutexError if initialisation of the contained mutex fails.
416  * (It is often not worth checking for this, as it means either memory
417  * is exhausted or pthread has run out of other resources to create
418  * new mutexes.)
419  */
420  Releaser(const Releaser& r) {}
421 
422 /**
423  * @exception std::bad_alloc The default constructor might throw
424  * std::bad_alloc if memory is exhausted and the system throws in that
425  * case.
426  * @exception Thread::MutexError The default constructor might throw
427  * Thread::MutexError if initialisation of the contained mutex fails.
428  * (It is often not worth checking for this, as it means either memory
429  * is exhausted or pthread has run out of other resources to create
430  * new mutexes.)
431  */
432  Releaser() {}
433 
434 /**
435  * The destructor does not throw provided that the destructors of any
436  * bound arguments of a functor managed by this Releaser object do not
437  * throw (as they should not do), and assuming that merely iterating
438  * through a list does not throw (as it would not on any sane
439  * implementation).
440  */
441  ~Releaser();
442 
443 /* Only has effect if --with-glib-memory-slices-compat or
444  * --with-glib-memory-slices-no-compat option picked */
446 };
447 
448 /* the emitter classes */
449 
450 /**
451  * @class EmitterArg emitter.h c++-gtk-utils/emitter.h
452  * @brief A class to execute callbacks connected to it, with provision
453  * for automatic disconnection.
454  * @sa SafeEmitterArg Releaser
455  * @sa emitter.h
456  * @sa Callback namespace
457  *
458  * Callback::FunctorArg objects may be connected to Emitter classes,
459  * and will be executed when EmitterArg<>::emit() or
460  * EmitterArg<>::operator()() are called.
461  *
462  * One version of the connect() method takes a Releaser object as an
463  * argument. Such a Releaser object should be a public member of any
464  * target class which wants functors representing any of its methods
465  * to be disconnected automatically from the EmitterArg object when
466  * the target class object is destroyed.
467  *
468  * A connection may be explicitly disconnected by calling the
469  * disconnect() method, and may also be temporarily blocked and
470  * subsequently unblocked with the block() and unblock() methods.
471  *
472  * The template type is the type of the unbound argument (or type
473  * container of unbound arguments), if any. EmitterArg<void> is
474  * typedef'ed to Emitter.
475  *
476  * @b Usage
477  *
478  * For a class my_obj of type MyClass, with a method void
479  * MyClass::my_method(int, const char*), usage for a fully bound functor
480  * and emitter would be:
481  *
482  * @code
483  * using namespace Cgu;
484  * int arg = 1;
485  * Emitter e;
486  * e.connect(Callback::make(my_obj, &MyClass::my_method, arg, "Hello\n"));
487  * e();
488  * @endcode
489  *
490  * Or for a partially bound functor and emitter:
491  *
492  * @code
493  * using namespace Cgu;
494  * int arg = 1;
495  * EmitterArg<const char*> e;
496  * e.connect(Callback::make(my_obj, &MyClass::my_method, arg));
497  * e("Hello\n");
498  * @endcode
499  *
500  * For further background, including about thread-safety, exception
501  * safety, the use of the Cgu::TypeTuple struct for calls involving
502  * two or three unbound arguments and other matters, read this:
503  * emitter.h, or for more information about bound and unbound
504  * arguments, read this: Cgu::Callback.
505  */
506 
507 template <class FreeArg>
508 class EmitterArg {
509 
510 #ifndef DOXYGEN_PARSING
511  // f1 is the functor we execute when we emit()
512  // f2 is the functor we execute in our destructor if we are destroyed
513  // before the remote object is
514  struct ListItem {
515  Callback::FunctorArg<FreeArg> f1;
517  bool blocked;
518  ListItem(Callback::FunctorArg<FreeArg> f1_, Callback::Functor f2_):
519  f1(f1_), f2(f2_), blocked(false) {}
520  };
521 #endif
522 
523  std::list<ListItem> emission_list;
524 
525  // only Releaser objects can access this
526  // TODO On an ABI break, change tracking_disconnect() to take a
527  // const Callback::Functor& argument: we can do this now that we
528  // have Callback::make_ref() available from version 1.2.13.
529  void tracking_disconnect(Callback::FunctorArg<FreeArg>);
530 
531  // emitters cannot be copied
532  EmitterArg(const EmitterArg&);
533  EmitterArg& operator=(const EmitterArg&);
534 public:
535  friend class Releaser;
536 
537 /**
538  * This will execute the connected functors.
539  * @param arg The argument to be passed to the referenced function or
540  * class method, if any.
541  * @exception std::bad_alloc The method might throw std::bad_alloc if
542  * memory is exhausted and the system throws in that case. In
543  * addition, it will throw if the functions or class methods
544  * referenced by the functors throw (or if the copy constructor of a
545  * free or bound argument throws and it is not a reference argument).
546  * @note This function is specialised for Emitter (ie
547  * EmitterArg<void>) to take no argument, and for
548  * EmitterArg<TypeTuple<T1, T2> > and EmitterArg<TypeTuple<T1, T2, T3>
549  * > to take two and three arguments respectively.
550  */
551  void operator()(typename Cgu::Param<FreeArg>::ParamType arg) const {emit(arg);}
552 
553 /**
554  * This will execute the connected functors.
555  * @param arg The argument to be passed to the referenced function or
556  * class method, if any.
557  * @exception std::bad_alloc The method might throw std::bad_alloc if
558  * memory is exhausted and the system throws in that case. In
559  * addition, it will throw if the functions or class methods
560  * referenced by the functors throw (or if the copy constructor of a
561  * free or bound argument throws and it is not a reference argument).
562  * @note This function is specialised for Emitter (ie
563  * EmitterArg<void>) to take no argument, and for
564  * EmitterArg<TypeTuple<T1, T2> > and EmitterArg<TypeTuple<T1, T2, T3>
565  * > to take two and three arguments respectively.
566  */
567  void emit(typename Cgu::Param<FreeArg>::ParamType arg) const;
568 
569 /**
570  * This will execute the connected functors, but it also reports
571  * whether in fact there were any connected functors to execute. (It
572  * is not necessary to use this function just because it is not known
573  * whether a functor is connected - if the standard emit() function is
574  * called when no functor is connected, nothing will happen. The
575  * feature of this method is that it will report the outcome.)
576  * @param arg The argument to be passed to the connected functions or
577  * class methods, if any.
578  * @return Returns false if there were no functors to execute, or true
579  * if functors have been executed.
580  * @exception std::bad_alloc The method might throw std::bad_alloc if
581  * memory is exhausted and the system throws in that case. In
582  * addition, it will throw if the functions or class methods
583  * referenced by the functors throw (or if the copy constructor of a
584  * free or bound argument throws and it is not a reference argument).
585  * @note This function is specialised for Emitter (ie
586  * EmitterArg<void>) to take no argument, and for
587  * EmitterArg<TypeTuple<T1, T2> > and EmitterArg<TypeTuple<T1, T2, T3>
588  * > to take two and three arguments respectively.
589  */
590  bool test_emit(typename Cgu::Param<FreeArg>::ParamType arg) const;
591 
592 /**
593  * Connects a functor.
594  * @param f The functor to connect.
595  * @return The functor connected.
596  * @exception std::bad_alloc The method might throw std::bad_alloc if
597  * memory is exhausted and the system throws in that case.
598  * @note This function is specialised for Emitter (ie
599  * EmitterArg<void>) to take and return a Callback::Functor argument,
600  * and for EmitterArg<TypeTuple<T1, T2> > and EmitterArg<TypeTuple<T1,
601  * T2, T3> > to take and return a Callback::FunctorArg<TypeTuple<T1,
602  * T2> > and Callback::FunctorArg<TypeTuple<T1, T2, T3> > argument
603  * respectively.
604  */
606 
607 /**
608  * Connects a functor.
609  * @param f The functor to connect.
610  * @param r A Releaser object for automatic disconnection of the
611  * functor if the object whose method it represents is destroyed.
612  * @return The functor connected.
613  * @exception std::bad_alloc The method might throw std::bad_alloc if
614  * memory is exhausted and the system throws in that case.
615  * @note This function is specialised for Emitter (ie
616  * EmitterArg<void>) to take and return a Callback::Functor argument,
617  * and for EmitterArg<TypeTuple<T1, T2> > and EmitterArg<TypeTuple<T1,
618  * T2, T3> > to take and return a Callback::FunctorArg<TypeTuple<T1,
619  * T2> > and Callback::FunctorArg<TypeTuple<T1, T2, T3> > argument
620  * respectively.
621  */
623 
624 /**
625  * Disconnects a functor previously connected. This does not throw
626  * provided that the destructors of any bound arguments do not throw
627  * (as they should not do), and assuming that merely iterating through
628  * a list does not throw (as it would not on any sane implementation).
629  * @param f The functor to disconnect.
630  * @note 1. If the same functor has been connected more than once to
631  * the same EmitterArg object, this call will disconnect all of them.
632  * @note 2. This function is specialised for Emitter (ie
633  * EmitterArg<void>) to take a Callback::Functor argument, and for
634  * EmitterArg<TypeTuple<T1, T2> > and EmitterArg<TypeTuple<T1, T2, T3>
635  * > to take a Callback::FunctorArg<TypeTuple<T1, T2> > and
636  * Callback::FunctorArg<TypeTuple<T1, T2, T3> > argument respectively.
637  */
639 
640 /**
641  * Blocks a connected functor from executing when emit() or
642  * operator()() is called until unblock() is called. This method does
643  * not throw (assuming that merely iterating through a list does not
644  * throw, as it would not on any sane implementation).
645  * @param f The functor to block.
646  * @note 1. If the same functor has been connected more than once to
647  * the same EmitterArg object, this call will block all of them.
648  * @note 2. This function is specialised for Emitter (ie
649  * EmitterArg<void>) to take a Callback::Functor argument, and for
650  * EmitterArg<TypeTuple<T1, T2> > and EmitterArg<TypeTuple<T1, T2, T3>
651  * > to take a Callback::FunctorArg<TypeTuple<T1, T2> > and
652  * Callback::FunctorArg<TypeTuple<T1, T2, T3> > argument respectively.
653  */
654  void block(const Callback::FunctorArg<FreeArg>& f);
655 
656 /**
657  * Unblocks a previously blocked functor. This method does not throw
658  * (assuming that merely iterating through a list does not throw, as
659  * it would not on any sane implementation).
660  * @param f The functor to unblock.
661  * @note 1. If the same functor has been connected more than once to
662  * the same EmitterArg object, this call will unblock all of them.
663  * @note 2. This function is specialised for Emitter (ie
664  * EmitterArg<void>) to take a Callback::Functor argument, and for
665  * EmitterArg<TypeTuple<T1, T2> > and EmitterArg<TypeTuple<T1, T2, T3>
666  * > to take a Callback::FunctorArg<TypeTuple<T1, T2> > and
667  * Callback::FunctorArg<TypeTuple<T1, T2, T3> > argument respectively.
668  */
669  void unblock(const Callback::FunctorArg<FreeArg>& f);
670 
671 /**
672  * @exception std::bad_alloc The constructor might throw
673  * std::bad_alloc if memory is exhausted and the system throws in that
674  * case.
675  */
677 
678 /**
679  * The destructor does not throw provided that the destructors of any
680  * bound arguments do not throw (as they should not do), and assuming
681  * that merely iterating through a list does not throw (as it would
682  * not on any sane implementation).
683  */
684  ~EmitterArg();
685 
686 /* Only has effect if --with-glib-memory-slices-compat or
687  * --with-glib-memory-slices-no-compat option picked */
689 };
690 
691 template <class FreeArg>
693 
694  struct DisconnectReleaserItem {
695  static void exec(const ListItem& l) {(l.f2)();}
696  };
697  std::for_each(emission_list.begin(), emission_list.end(),
699 }
700 
701 template <class FreeArg>
703 
704  // create a local copy of emission_list, to enable a connected
705  // function (i) to delete the EmitterArg<> object to which it is
706  // connected, even if there are other functors still to execute in
707  // the same emission (which will execute normally provided they do
708  // not try to call any of the emitter's functions), (ii) to call
709  // 'delete this' nothwithstanding that the connected function is
710  // protected by a Releaser object (assuming all the other restraints
711  // on calling 'delete this' are met), provided that no other access
712  // would be made to the deleted object in a function call connected
713  // to the same emitter which is due to execute subsequently in the
714  // same emission, and (iii) to disconnect itself from the
715  // EmitterArg<> object. This design approach has a trade-off: if a
716  // connected function tries to block, unblock or disconnect another
717  // function connected to the same EmitterArg<> object which is due
718  // to execute subsequently in the same emission (or to block,
719  // unblock or disconnect itself when it is due to execute again
720  // subsequently in the same emission), the attempted block, unblock
721  // or disconnection will not have any effect on that emission (it
722  // will only have effect on a subsequent emission). In addition, a
723  // connected function may not destroy an object whose non-static
724  // method is connected to the same emitter and which would execute
725  // subsequently in the same emission, even if that object is
726  // protected by a Releaser object (the non-static method will
727  // unsuccessfully attempt to execute notwithstanding the destruction
728  // of the object it would be operating on).
729 
730  std::list<ListItem> local_list = emission_list;
731 
732  // don't use std::bind2nd()/std::ptr_fun() with std::for_each()
733  // or we cannot use reference arguments - iterate by hand
734  typename std::list<ListItem>::const_iterator iter;
735  for (iter = local_list.begin(); iter != local_list.end(); ++iter) {
736  if (!iter->blocked) iter->f1(arg);
737  }
738 }
739 
740 template <class FreeArg>
742  if (emission_list.empty()) return false;
743  emit(arg);
744  return true;
745 }
746 
747 template <class FreeArg>
749  emission_list.push_back(ListItem(f1, Callback::Functor()));
750  return f1;
751 }
752 
753 template <class FreeArg>
754 Callback::FunctorArg<FreeArg> EmitterArg<FreeArg>::connect(const Callback::FunctorArg<FreeArg>& f1, Releaser& r) {
755  // In this method:
756  // f1 is the functor we execute when we emit()
757  // f2 is the functor we execute in our destructor if we are destroyed before the
758  // remote object is
759  // f3 is the functor the remote object executes in its Releaser if it is destroyed
760  // before we are, or if Releaser::operator=() is called
761 
762  Callback::SafeFunctor f3(Callback::make_ref(*this, &EmitterArg<FreeArg>::tracking_disconnect, f1));
763  Callback::Functor f2(Callback::make_ref(r, &Releaser::remove, f3));
764  r.add(f3);
765  try {
766  emission_list.push_back(ListItem(f1, f2));
767  }
768  catch (...) {
769  r.remove(f3);
770  throw;
771  }
772  return f1;
773 }
774 
775 template <class FreeArg>
777  // we don't have lambdas in C++03, so use a struct in function scope
778  struct Pred {
779  // we can't pass const reference types as we bind with std::bind2nd below
780  static bool pred(ListItem p, Callback::FunctorArg<FreeArg> f) {
781  return (p.f1 == f);
782  }
783  };
784 
785  // in theory, we could have connected the same functor object
786  // more than once, so cater for that
787  typename std::list<ListItem>::iterator iter = emission_list.begin();
788  for (;;) {
789  iter = std::find_if(iter, emission_list.end(),
790  std::bind2nd(std::ptr_fun(Pred::pred), arg));
791  if (iter != emission_list.end()) {
792  // remove ourselves from the remote Releaser object
793  (iter->f2)();
794 
795  // remove this item from emission_list
796  iter = emission_list.erase(iter);
797  }
798  else break;
799  }
800 }
801 
802 // tracking disconnect() is the same as disconnect(), except that we do not
803 // execute f2 as the remote Releaser object will destroy its own functors
804 // in that case
805 template <class FreeArg>
807  // we don't have lambdas in C++03, so use a struct in function scope
808  struct Pred {
809  // we can't pass const reference types as we bind with std::bind2nd below
810  static bool pred(ListItem p, Callback::FunctorArg<FreeArg> f) {
811  return (p.f1 == f);
812  }
813  };
814 
815  typename std::list<ListItem>::iterator iter = emission_list.begin();
816  for (;;) {
817  iter = std::find_if(iter, emission_list.end(),
818  std::bind2nd(std::ptr_fun(Pred::pred), arg));
819  if (iter != emission_list.end()) {
820  // remove this item from emission_list
821  iter = emission_list.erase(iter);
822  }
823  else break;
824  }
825 }
826 
827 template <class FreeArg>
829  // we don't have lambdas in C++03, so use a struct in function scope
830  struct Pred {
831  // we can't pass const reference types as we bind with std::bind2nd below
832  static bool pred(ListItem p, Callback::FunctorArg<FreeArg> f) {
833  return (p.f1 == f);
834  }
835  };
836 
837  // in theory, we could have connected the same functor object
838  // more than once, so cater for that
839  typename std::list<ListItem>::iterator iter = emission_list.begin();
840  for (;;) {
841  iter = std::find_if(iter, emission_list.end(),
842  std::bind2nd(std::ptr_fun(Pred::pred), arg));
843  if (iter != emission_list.end()) {
844  iter->blocked = true;
845  ++iter;
846  }
847  else break;
848  }
849 }
850 
851 template <class FreeArg>
853  // we don't have lambdas in C++03, so use a struct in function scope
854  struct Pred {
855  // we can't pass const reference types as we bind with std::bind2nd below
856  static bool pred(ListItem p, Callback::FunctorArg<FreeArg> f) {
857  return (p.f1 == f);
858  }
859  };
860 
861  // in theory, we could have connected the same functor object
862  // more than once, so cater for that
863  typename std::list<ListItem>::iterator iter = emission_list.begin();
864  for (;;) {
865  iter = std::find_if(iter, emission_list.end(),
866  std::bind2nd(std::ptr_fun(Pred::pred), arg));
867  if (iter != emission_list.end()) {
868  iter->blocked = false;
869  ++iter;
870  }
871  else break;
872  }
873 }
874 
875 /**
876  * @class SafeEmitterArg emitter.h c++-gtk-utils/emitter.h
877  * @brief A thread-safe class to execute callbacks connected to it,
878  * with provision for automatic disconnection.
879  * @sa EmitterArg Releaser
880  * @sa emitter.h
881  * @sa Callback namespace
882  *
883  * This is a thread-safe version of the EmitterArg class.
884  * Callback::SafeFunctorArg objects may be connected to SafeEmitter
885  * classes, and will be executed when SafeEmitterArg<>::emit() or
886  * SafeEmitterArg<>::operator()() are called.
887  *
888  * One version of the connect() method takes a Releaser object as an
889  * argument. Such a Releaser object should be a public member of any
890  * target class which wants functors representing any of its methods
891  * to be disconnected automatically from the SafeEmitterArg object
892  * when the target class object is destroyed.
893  *
894  * A connection may be explicitly disconnected by calling the
895  * disconnect() method, and may also be temporarily blocked and
896  * subsequently unblocked with the block() and unblock() methods.
897  *
898  * The template type is the type of the unbound argument (or type
899  * container of unbound arguments), if any. SafeEmitterArg<void> is
900  * typedef'ed to SafeEmitter.
901  *
902  * @b Usage
903  *
904  * For a class my_obj of type MyClass, with a method void
905  * MyClass::my_method(int, const char*), usage for a fully bound
906  * functor and emitter would be:
907  *
908  * @code
909  * using namespace Cgu;
910  * int arg = 1;
911  * SafeEmitter se;
912  * se.connect(Callback::make(my_obj, &MyClass::my_method, arg, "Hello\n"));
913  * se();
914  * @endcode
915  *
916  * Or for a partially bound functor and emitter:
917  *
918  * @code
919  * using namespace Cgu;
920  * int arg = 1;
921  * SafeEmitterArg<const char*> se;
922  * se.connect(Callback::make(my_obj, &MyClass::my_method, arg));
923  * se("Hello\n");
924  * @endcode
925  *
926  * For further background, including about thread-safety, exception
927  * safety, the use of the Cgu::TypeTuple struct for calls involving
928  * two or three unbound arguments and other matters, read this:
929  * emitter.h
930  */
931 
932 template <class FreeArg>
933 class SafeEmitterArg {
934 
935 #ifndef DOXYGEN_PARSING
936  // f1 is the functor we execute when we emit()
937  // f2 is the functor we execute in our destructor if we are destroyed
938  // before the remote object is
939  struct ListItem {
942  bool blocked;
944  f1(f1_), f2(f2_), blocked(false) {}
945  };
946 #endif
947 
948  std::list<ListItem> emission_list;
949  mutable Thread::Mutex mutex; // make this mutable so we can lock/unlock in const methods
950 
951  // only Releaser objects can access this
952  // TODO On an ABI break, change tracking_disconnect() to take a
953  // const Callback::SafeFunctor& argument: we can do this now that we
954  // have Callback::make_ref() available from version 1.2.13.
955  void tracking_disconnect(Callback::SafeFunctorArg<FreeArg>);
956 
957  // emitters cannot be copied
959  SafeEmitterArg& operator=(const SafeEmitterArg&);
960 public:
961  friend class Releaser;
962 
963 /**
964  * This will execute the connected functors. It is thread safe if the
965  * functions or class methods referenced by the connected functors are
966  * thread safe.
967  * @param arg The argument, if any, to be passed to the functions or
968  * class methods referenced by the connected functors.
969  * @exception std::bad_alloc The method might throw std::bad_alloc if
970  * memory is exhausted and the system throws in that case. In
971  * addition, it will throw if the functions or class methods
972  * referenced by the functors throw (or if the copy constructor of a
973  * free or bound argument throws and it is not a reference argument).
974  * @note This function is specialised for SafeEmitter (ie
975  * SafeEmitterArg<void>) to take no argument, and for
976  * SafeEmitterArg<TypeTuple<T1, T2> > and SafeEmitterArg<TypeTuple<T1,
977  * T2, T3> > to take two and three arguments respectively.
978  */
979  void operator()(typename Cgu::Param<FreeArg>::ParamType arg) const {emit(arg);}
980 
981 /**
982  * This will execute the connected functors. It is thread safe if the
983  * functions or class methods referenced by the connected functors are
984  * thread safe.
985  * @param arg The argument to be passed to the referenced function or
986  * class method, if any.
987  * @exception std::bad_alloc The method might throw std::bad_alloc if
988  * memory is exhausted and the system throws in that case. In
989  * addition, it will throw if the functions or class methods
990  * referenced by the functors throw (or if the copy constructor of a
991  * free or bound argument throws and it is not a reference argument).
992  * @note This function is specialised for SafeEmitter (ie
993  * SafeEmitterArg<void>) to take no argument, and for
994  * SafeEmitterArg<TypeTuple<T1, T2> > and SafeEmitterArg<TypeTuple<T1,
995  * T2, T3> > to take two and three arguments respectively.
996  */
997  void emit(typename Cgu::Param<FreeArg>::ParamType arg) const;
998 
999 /**
1000  * This will execute the connected functors, but it also reports
1001  * whether in fact there were any connected functors to execute. It
1002  * is thread safe if the functions or class methods referenced by the
1003  * connected functors are thread safe. (It is not necessary to use
1004  * this function just because it is not known whether a functor is
1005  * connected - if the standard emit() function is called when no
1006  * functor is connected, nothing will happen. The feature of this
1007  * method is that it will report the outcome.)
1008  * @param arg The argument to be passed to the connected functions or
1009  * class methods, if any.
1010  * @return Returns false if there were no functors to execute, or true
1011  * if functors have been executed.
1012  * @exception std::bad_alloc The method might throw std::bad_alloc if
1013  * memory is exhausted and the system throws in that case. In
1014  * addition, it will throw if the functions or class methods
1015  * referenced by the functors throw (or if the copy constructor of a
1016  * free or bound argument throws and it is not a reference argument).
1017  * @note This function is specialised for SafeEmitter (ie
1018  * SafeEmitterArg<void>) to take no argument, and for
1019  * SafeEmitterArg<TypeTuple<T1, T2> > and SafeEmitterArg<TypeTuple<T1,
1020  * T2, T3> > to take two and three arguments respectively.
1021  */
1022  bool test_emit(typename Cgu::Param<FreeArg>::ParamType arg) const;
1023 
1024 /**
1025  * Connects a functor. It is thread safe.
1026  * @param f The functor to connect.
1027  * @return The functor connected.
1028  * @exception std::bad_alloc The method might throw std::bad_alloc if
1029  * memory is exhausted and the system throws in that case.
1030  * @note This function is specialised for SafeEmitter (ie
1031  * SafeEmitterArg<void>) to take and return a Callback::SafeFunctor
1032  * argument, and for SafeEmitterArg<TypeTuple<T1, T2> > and
1033  * SafeEmitterArg<TypeTuple<T1, T2, T3> > to take and return a
1034  * Callback::SafeFunctorArg<TypeTuple<T1, T2> > and
1035  * Callback::SafeFunctorArg<TypeTuple<T1, T2, T3> > argument
1036  * respectively.
1037  */
1039 
1040 /**
1041  * Connects a functor. It is thread safe.
1042  * @param f The functor to connect.
1043  * @param r A Releaser object for automatic disconnection of the
1044  * functor if the object whose method it represents is destroyed.
1045  * @return The functor connected.
1046  * @exception std::bad_alloc The method might throw std::bad_alloc if
1047  * memory is exhausted and the system throws in that case.
1048  * @note This function is specialised for SafeEmitter (ie
1049  * SafeEmitterArg<void>) to take and return a Callback::SafeFunctor
1050  * argument, and for SafeEmitterArg<TypeTuple<T1, T2> > and
1051  * SafeEmitterArg<TypeTuple<T1, T2, T3> > to take and return a
1052  * Callback::SafeFunctorArg<TypeTuple<T1, T2> > and
1053  * Callback::SafeFunctorArg<TypeTuple<T1, T2, T3> > argument
1054  * respectively.
1055  */
1057 
1058 /**
1059  * Disconnects a functor previously connected. This does not throw
1060  * provided that the destructors of any bound arguments do not throw
1061  * (as they should not do), and assuming that merely iterating through
1062  * a list does not throw (as it would not on any sane implementation).
1063  * It is thread safe.
1064  * @param f The functor to disconnect.
1065  * @note 1. If the same functor has been connected more than once to
1066  * the same SafeEmitterArg object, this call will disconnect all of
1067  * them.
1068  * @note 2. This function is specialised for SafeEmitter (ie
1069  * SafeEmitterArg<void>) to take a Callback::SafeFunctor argument, and
1070  * for SafeEmitterArg<TypeTuple<T1, T2> > and
1071  * SafeEmitterArg<TypeTuple<T1, T2, T3> > to take a
1072  * Callback::SafeFunctorArg<TypeTuple<T1, T2> > and
1073  * Callback::SafeFunctorArg<TypeTuple<T1, T2, T3> > argument
1074  * respectively.
1075  */
1077 
1078 /**
1079  * Blocks a connected functor from executing when emit() or
1080  * operator()() is called until unblock() is called. This method does
1081  * not throw (assuming that merely iterating through a list does not
1082  * throw, as it would not on any sane implementation). It is thread
1083  * safe.
1084  * @param f The functor to block.
1085  * @note 1. If the same functor has been connected more than once to
1086  * the same SafeEmitterArg object, this call will block all of them.
1087  * @note 2. This function is specialised for SafeEmitter (ie
1088  * SafeEmitterArg<void>) to take a Callback::SafeFunctor argument, and
1089  * for SafeEmitterArg<TypeTuple<T1, T2> > and
1090  * SafeEmitterArg<TypeTuple<T1, T2, T3> > to take a
1091  * Callback::SafeFunctorArg<TypeTuple<T1, T2> > and
1092  * Callback::SafeFunctorArg<TypeTuple<T1, T2, T3> > argument
1093  * respectively.
1094  */
1096 
1097 /**
1098  * Unblocks a previously blocked functor. This method does not throw
1099  * (assuming that merely iterating through a list does not throw, as
1100  * it would not on any sane implementation). It is thread safe.
1101  * @param f The functor to unblock.
1102  * @note 1. If the same functor has been connected more than once to
1103  * the same SafeEmitterArg object, this call will unblock all of them.
1104  * @note 2. This function is specialised for SafeEmitter (ie
1105  * SafeEmitterArg<void>) to take a Callback::SafeFunctor argument, and
1106  * for SafeEmitterArg<TypeTuple<T1, T2> > and
1107  * SafeEmitterArg<TypeTuple<T1, T2, T3> > to take a
1108  * Callback::SafeFunctorArg<TypeTuple<T1, T2> > and
1109  * Callback::SafeFunctorArg<TypeTuple<T1, T2, T3> > argument
1110  * respectively.
1111  */
1113 
1114 /**
1115  * @exception std::bad_alloc The constructor might throw
1116  * std::bad_alloc if memory is exhausted and the system throws in that
1117  * case.
1118  * @exception Thread::MutexError The constructor might throw
1119  * Thread::MutexError if initialisation of the contained mutex fails.
1120  * (It is often not worth checking for this, as it means either memory
1121  * is exhausted or pthread has run out of other resources to create
1122  * new mutexes.)
1123  */
1125 
1126 /**
1127  * The destructor does not throw provided that the destructors of any
1128  * bound arguments do not throw (as they should not do), and assuming
1129  * that merely iterating through a list does not throw (as it would
1130  * not on any sane implementation). It is thread-safe as regards the
1131  * dropping of any connected functors and of any relevant Releaser
1132  * objects.
1133  */
1134  ~SafeEmitterArg();
1135 
1136 /* Only has effect if --with-glib-memory-slices-compat or
1137  * --with-glib-memory-slices-no-compat option picked */
1139 };
1140 
1141 template <class FreeArg>
1143 
1144  // go through emission_list() item by item, popping off the front and erasing
1145  // as we go in case Releaser::try_remove() fails to acquire the lock on one
1146  // of the iterations
1147  Thread::Mutex::Lock lock(mutex);
1148  while (!emission_list.empty()) {
1149  typename std::list<ListItem>::iterator iter = emission_list.begin();
1150  int result = 0; // f2 might be a no-op
1151  // remove ourselves from the remote Releaser object
1152  (iter->f2)(&result);
1153  if (!result) { // we got the Releaser mutex lock or no-op
1154  // now remove this item from emission_list
1155  emission_list.erase(iter);
1156  }
1157  else {
1158  mutex.unlock();
1159  // spin nicely
1160 #ifdef CGU_USE_SCHED_YIELD
1161  sched_yield();
1162 #else
1163  usleep(10);
1164 #endif
1165  mutex.lock();
1166  }
1167  }
1168 }
1169 
1170 template <class FreeArg>
1172 
1173  // create a local copy of emission_list, to enable a connected
1174  // function (i) to delete the EmitterArg<> object to which it is
1175  // connected, even if there are other functors still to execute in
1176  // the same emission (which will execute normally provided they do
1177  // not try to call any of the emitter's functions), (ii) to call
1178  // 'delete this' nothwithstanding that the connected function is
1179  // protected by a Releaser object (assuming all the other restraints
1180  // on calling 'delete this' are met), provided that no other access
1181  // would be made to the deleted object in a function call connected
1182  // to the same emitter which is due to execute subsequently in the
1183  // same emission, and (iii) to disconnect itself from the
1184  // EmitterArg<> object. This design approach has a trade-off: if a
1185  // connected function tries to block, unblock or disconnect another
1186  // function connected to the same EmitterArg<> object which is due
1187  // to execute subsequently in the same emission (or to block,
1188  // unblock or disconnect itself when it is due to execute again
1189  // subsequently in the same emission), the attempted block, unblock
1190  // or disconnection will not have any effect on that emission (it
1191  // will only have effect on a subsequent emission). In addition, a
1192  // connected function may not destroy an object whose non-static
1193  // method is connected to the same emitter and which would execute
1194  // subsequently in the same emission, even if that object is
1195  // protected by a Releaser object (the non-static method will
1196  // unsuccessfully attempt to execute notwithstanding the destruction
1197  // of the object it would be operating on).
1198 
1199  // SafeFunctorArg<> usage has the additional point that while an
1200  // emission is in course, another thread should not try to do any of
1201  // those things, or the same outcome will result. Another thread
1202  // should leave alone objects connected to a SafeEmitterArg<> object
1203  // from the time of operator()() or emit() beginning to the time of
1204  // it ending, and not try to interfere.
1205 
1206  // a side effect of having a local list is that, as required, we
1207  // will not be holding our mutex when executing the functors it
1208  // contains. It is OK having the functors in two different lists
1209  // which are potentially (when our mutex is released) in two
1210  // different threads, because the functors hold their
1211  // Callback::Callback objects by SharedLockPtr so their reference
1212  // count is protected (they are SafeFunctorArg<> functors).
1213 
1214  // we could reduce contention on the mutex by allocating local_list
1215  // outside the mutex, eg by taking the size of emission_list within
1216  // the mutex, then allocating the nodes of local_list outside the
1217  // mutex with that size, and then copying items across within the
1218  // mutex (checking the end iterators of both containers when
1219  // iterating because the size of emitter_list could have changed
1220  // while allocating local_list) and, if the size of emission list
1221  // did change by another thread disconnecting a functor in the
1222  // interval when local_list was allocated, resizing local_list
1223  // downwards with std::list::resize(). However this is mostly
1224  // pointless, because although this arrangement would be as equally
1225  // thread-safe as the implementation below and lessen contention,
1226  // since you don't know exactly what functors will be executed
1227  // anyway if functors are added or removed by one thread while
1228  // another is emitting, such concurrent emitting is not a practice
1229  // to make special provision for. Accordingly, we go the simpler,
1230  // more naive route below.
1231 
1232  std::list<ListItem> local_list;
1233  { // scope block for mutex lock
1234  Thread::Mutex::Lock lock(mutex);
1235  local_list = emission_list;
1236  }
1237 
1238  // don't use std::bind2nd()/std::ptr_fun() with std::for_each()
1239  // or we cannot use reference arguments - iterate by hand
1240  typename std::list<ListItem>::const_iterator iter;
1241  for (iter = local_list.begin(); iter != local_list.end(); ++iter) {
1242  if (!iter->blocked) iter->f1(arg);
1243  }
1244 }
1245 
1246 template <class FreeArg>
1248 
1249  std::list<ListItem> local_list;
1250  { // scope block for mutex lock
1251  Thread::Mutex::Lock lock(mutex);
1252  if (emission_list.empty()) return false;
1253  local_list = emission_list;
1254  }
1255 
1256  // don't use std::bind2nd()/std::ptr_fun() with std::for_each()
1257  // or we cannot use reference arguments - iterate by hand
1258  typename std::list<ListItem>::const_iterator iter;
1259  for (iter = local_list.begin(); iter != local_list.end(); ++iter) {
1260  if (!iter->blocked) iter->f1(arg);
1261  }
1262  return true;
1263 }
1264 
1265 template <class FreeArg>
1267  // construct the new node outside the mutex to reduce contention and
1268  // then splice it at the end
1269  std::list<ListItem> tmp;
1270  tmp.push_back(ListItem(f1, Callback::SafeFunctorArg<int*>()));
1271  Thread::Mutex::Lock lock(mutex);
1272  emission_list.splice(emission_list.end(), tmp);
1273  return f1;
1274 }
1275 
1276 template <class FreeArg>
1277 Callback::SafeFunctorArg<FreeArg> SafeEmitterArg<FreeArg>::connect(const Callback::SafeFunctorArg<FreeArg>& f1, Releaser& r) {
1278  // In this method:
1279  // f1 is the functor we execute when we emit()
1280  // f2 is the functor we execute in our destructor if we are destroyed before the
1281  // remote object is
1282  // f3 is the functor the remote object executes in its Releaser if it is destroyed
1283  // before we are, or if Releaser::operator=() is called
1284 
1285  Callback::SafeFunctor f3(Callback::make_ref(*this, &SafeEmitterArg<FreeArg>::tracking_disconnect, f1));
1286  Callback::SafeFunctorArg<int*> f2(Callback::make_ref(r, &Releaser::try_remove, f3));
1287  // we can't call Releaser::add() when holding our mutex or we will
1288  // get out of order locking, as Releaser's mutex is acquired in that
1289  // method, and we don't need to do so
1290  r.add(f3);
1291  try {
1292  // construct the new node outside the mutex to reduce contention
1293  // and then splice it at the end
1294  std::list<ListItem> tmp;
1295  tmp.push_back(ListItem(f1, f2));
1296  Thread::Mutex::Lock lock(mutex);
1297  emission_list.splice(emission_list.end(), tmp);
1298  }
1299  catch (...) {
1300  r.remove(f3);
1301  throw;
1302  }
1303  return f1;
1304 }
1305 
1306 template <class FreeArg>
1308  // we don't have lambdas in C++03, so use a struct in function scope
1309  struct Pred {
1310  // we can't pass const reference types as we bind with std::bind2nd below
1311  static bool pred(ListItem p, Callback::SafeFunctorArg<FreeArg> f) {
1312  return (p.f1 == f);
1313  }
1314  };
1315 
1316  // in theory, we could have connected the same functor object more than
1317  // once, so cater for that as well as Releaser::try_remove() failing
1318  Thread::Mutex::Lock lock(mutex);
1319  typename std::list<ListItem>::iterator iter = emission_list.begin();
1320  for(;;) {
1321  iter = std::find_if(iter, emission_list.end(),
1322  std::bind2nd(std::ptr_fun(Pred::pred), arg));
1323  if (iter != emission_list.end()) {
1324  int result = 0; // f2 might be a no-op
1325  // remove ourselves from the remote Releaser object
1326  (iter->f2)(&result);
1327  if (!result) { // we got the Releaser mutex lock or no-op
1328  // now remove this item from emission_list
1329  iter = emission_list.erase(iter);
1330  }
1331  else {
1332  mutex.unlock();
1333  // spin nicely
1334 #ifdef CGU_USE_SCHED_YIELD
1335  sched_yield();
1336 #else
1337  usleep(10);
1338 #endif
1339  mutex.lock();
1340  // start again at the beginning - we have released the mutex
1341  // so our iterator may have become invalid
1342  iter = emission_list.begin();
1343  }
1344  }
1345  else break;
1346  }
1347 }
1348 
1349 // tracking disconnect() is the same as disconnect(), except that we do not
1350 // execute f2 as the remote Releaser object will destroy its own functors
1351 // in that case
1352 template <class FreeArg>
1354  // we don't have lambdas in C++03, so use a struct in function scope
1355  struct Pred {
1356  // we can't pass const reference types as we bind with std::bind2nd below
1357  static bool pred(ListItem p, Callback::SafeFunctorArg<FreeArg> f) {
1358  return (p.f1 == f);
1359  }
1360  };
1361 
1362  Thread::Mutex::Lock lock(mutex);
1363  typename std::list<ListItem>::iterator iter = emission_list.begin();
1364  for (;;) {
1365  iter = std::find_if(iter, emission_list.end(),
1366  std::bind2nd(std::ptr_fun(Pred::pred), arg));
1367  if (iter != emission_list.end()) {
1368  // remove this item from emission_list
1369  iter = emission_list.erase(iter);
1370  }
1371  else break;
1372  }
1373 }
1374 
1375 template <class FreeArg>
1377  // we don't have lambdas in C++03, so use a struct in function scope
1378  struct Pred {
1379  // we can't pass const reference types as we bind with std::bind2nd below
1380  static bool pred(ListItem p, Callback::SafeFunctorArg<FreeArg> f) {
1381  return (p.f1 == f);
1382  }
1383  };
1384 
1385  // in theory, we could have connected the same functor object
1386  // more than once, so cater for that
1387  Thread::Mutex::Lock lock(mutex);
1388  typename std::list<ListItem>::iterator iter = emission_list.begin();
1389  for (;;) {
1390  iter = std::find_if(iter, emission_list.end(),
1391  std::bind2nd(std::ptr_fun(Pred::pred), arg));
1392  if (iter != emission_list.end()) {
1393  iter->blocked = true;
1394  ++iter;
1395  }
1396  else break;
1397  }
1398 }
1399 
1400 template <class FreeArg>
1402  // we don't have lambdas in C++03, so use a struct in function scope
1403  struct Pred {
1404  // we can't pass const reference types as we bind with std::bind2nd below
1405  static bool pred(ListItem p, Callback::SafeFunctorArg<FreeArg> f) {
1406  return (p.f1 == f);
1407  }
1408  };
1409 
1410  // in theory, we could have connected the same functor object
1411  // more than once, so cater for that
1412  Thread::Mutex::Lock lock(mutex);
1413  typename std::list<ListItem>::iterator iter = emission_list.begin();
1414  for (;;) {
1415  iter = std::find_if(iter, emission_list.end(),
1416  std::bind2nd(std::ptr_fun(Pred::pred), arg));
1417  if (iter != emission_list.end()) {
1418  iter->blocked = false;
1419  ++iter;
1420  }
1421  else break;
1422  }
1423 }
1424 
1425 #ifndef DOXYGEN_PARSING
1426 
1427 /* specialisations of EmitterArg and SafeEmitterArg for 0, 2 and 3
1428  unbound arguments */
1429 
1430 /* TODO: we could implement this better by passing all the ListItem
1431  * operations (including in the connect(), disconnect(), block() and
1432  * unblock() methods and so forth) into a separate templated class
1433  * which could be incorporated by composition or inheritance into
1434  * EmitterArg, which would avoid much of the code duplication arising
1435  * from the specialisations for 2 and 3 unbound arguments as added in
1436  * version 1.2.10: the only functions we actually need to specialise
1437  * for these additional arguments are the emit() ones. However, as
1438  * these classes are not PODSs this would give rise to binary breakage
1439  * of 1.2.9 and earlier, so we have to await a suitable ABI breakage
1440  * release to clean this up.
1441  */
1442 
1443 template <>
1444 class EmitterArg<void> {
1445  struct ListItem {
1446  Callback::Functor f1;
1447  Callback::Functor f2;
1448  bool blocked;
1449  ListItem(Callback::Functor f1_, Callback::Functor f2_):
1450  f1(f1_), f2(f2_), blocked(false) {}
1451  };
1452 
1453  std::list<ListItem> emission_list;
1454 
1455  void tracking_disconnect(Callback::Functor);
1456 
1457  EmitterArg(const EmitterArg&);
1458  EmitterArg& operator=(const EmitterArg&);
1459 public:
1460  friend class Releaser;
1461 
1462  void operator()() const {emit();}
1463  void emit() const;
1464 
1465  bool test_emit() const;
1466 
1469  void disconnect(const Callback::Functor&);
1470 
1471  void block(const Callback::Functor&);
1472  void unblock(const Callback::Functor&);
1473 
1474  EmitterArg() {}
1475  ~EmitterArg();
1476 
1477 /* Only has effect if --with-glib-memory-slices-compat or
1478  * --with-glib-memory-slices-no-compat option picked */
1480 };
1481 
1482 template <class FreeArg1, class FreeArg2>
1483 class EmitterArg <TypeTuple<FreeArg1, FreeArg2> > {
1484  struct ListItem {
1485  Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> > f1;
1486  Callback::Functor f2;
1487  bool blocked;
1488  ListItem(Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> > f1_, Callback::Functor f2_):
1489  f1(f1_), f2(f2_), blocked(false) {}
1490  };
1491 
1492  std::list<ListItem> emission_list;
1493 
1494  void tracking_disconnect(Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> >);
1495 
1496  EmitterArg(const EmitterArg&);
1497  EmitterArg& operator=(const EmitterArg&);
1498 public:
1499  friend class Releaser;
1500 
1501  void operator()(typename Cgu::Param<FreeArg1>::ParamType arg1,
1502  typename Cgu::Param<FreeArg2>::ParamType arg2) const {
1503  emit(arg1, arg2);
1504  }
1505  void emit(typename Cgu::Param<FreeArg1>::ParamType arg1,
1506  typename Cgu::Param<FreeArg2>::ParamType arg2) const;
1507 
1508  bool test_emit(typename Cgu::Param<FreeArg1>::ParamType arg1,
1509  typename Cgu::Param<FreeArg2>::ParamType arg2) const;
1510 
1511  Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> > connect(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> >& f);
1512  Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> > connect(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> >& f, Releaser& r);
1513  void disconnect(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> >& f);
1514 
1515  void block(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> >& f);
1516  void unblock(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> >& f);
1517 
1518  EmitterArg() {}
1519  ~EmitterArg();
1520 
1521 /* Only has effect if --with-glib-memory-slices-compat or
1522  * --with-glib-memory-slices-no-compat option picked */
1524 };
1525 
1526 template <class FreeArg1, class FreeArg2>
1527 EmitterArg<TypeTuple<FreeArg1, FreeArg2> >::~EmitterArg() {
1528 
1529  struct DisconnectReleaserItem {
1530  static void exec(const ListItem& l) {(l.f2)();}
1531  };
1532  std::for_each(emission_list.begin(), emission_list.end(),
1534 }
1535 
1536 template <class FreeArg1, class FreeArg2>
1537 void EmitterArg<TypeTuple<FreeArg1, FreeArg2> >::emit(typename Cgu::Param<FreeArg1>::ParamType arg1,
1538  typename Cgu::Param<FreeArg2>::ParamType arg2) const {
1539  std::list<ListItem> local_list = emission_list;
1540 
1541  typename std::list<ListItem>::const_iterator iter;
1542  for (iter = local_list.begin(); iter != local_list.end(); ++iter) {
1543  if (!iter->blocked) iter->f1(arg1, arg2);
1544  }
1545 }
1546 
1547 template <class FreeArg1, class FreeArg2>
1548 bool EmitterArg<TypeTuple<FreeArg1, FreeArg2> >::test_emit(typename Cgu::Param<FreeArg1>::ParamType arg1,
1549  typename Cgu::Param<FreeArg2>::ParamType arg2) const {
1550  if (emission_list.empty()) return false;
1551  emit(arg1, arg2);
1552  return true;
1553 }
1554 
1555 template <class FreeArg1, class FreeArg2>
1556 Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> > EmitterArg<TypeTuple<FreeArg1, FreeArg2> >::connect(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> >& f1) {
1557  emission_list.push_back(ListItem(f1, Callback::Functor()));
1558  return f1;
1559 }
1560 
1561 template <class FreeArg1, class FreeArg2>
1562 Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> > EmitterArg<TypeTuple<FreeArg1, FreeArg2> >::connect(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> >& f1, Releaser& r) {
1563  // In this method:
1564  // f1 is the functor we execute when we emit()
1565  // f2 is the functor we execute in our destructor if we are destroyed before the
1566  // remote object is
1567  // f3 is the functor the remote object executes in its Releaser if it is destroyed
1568  // before we are, or if Releaser::operator=() is called
1569 
1570  Callback::SafeFunctor f3(Callback::make_ref(*this, &EmitterArg<TypeTuple<FreeArg1, FreeArg2> >::tracking_disconnect, f1));
1571  Callback::Functor f2(Callback::make_ref(r, &Releaser::remove, f3));
1572  r.add(f3);
1573  try {
1574  emission_list.push_back(ListItem(f1, f2));
1575  }
1576  catch (...) {
1577  r.remove(f3);
1578  throw;
1579  }
1580  return f1;
1581 }
1582 
1583 template <class FreeArg1, class FreeArg2>
1584 void EmitterArg<TypeTuple<FreeArg1, FreeArg2> >::disconnect(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> >& arg) {
1585  struct Pred {
1586  static bool pred(ListItem p, Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> > f) {
1587  return (p.f1 == f);
1588  }
1589  };
1590 
1591  typename std::list<ListItem>::iterator iter = emission_list.begin();
1592  for (;;) {
1593  iter = std::find_if(iter, emission_list.end(),
1594  std::bind2nd(std::ptr_fun(Pred::pred), arg));
1595  if (iter != emission_list.end()) {
1596  (iter->f2)();
1597  iter = emission_list.erase(iter);
1598  }
1599  else break;
1600  }
1601 }
1602 
1603 template <class FreeArg1, class FreeArg2>
1604 void EmitterArg<TypeTuple<FreeArg1, FreeArg2> >::tracking_disconnect(Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> > arg) {
1605  struct Pred {
1606  static bool pred(ListItem p, Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> > f) {
1607  return (p.f1 == f);
1608  }
1609  };
1610 
1611  typename std::list<ListItem>::iterator iter = emission_list.begin();
1612  for (;;) {
1613  iter = std::find_if(iter, emission_list.end(),
1614  std::bind2nd(std::ptr_fun(Pred::pred), arg));
1615  if (iter != emission_list.end()) {
1616  iter = emission_list.erase(iter);
1617  }
1618  else break;
1619  }
1620 }
1621 
1622 template <class FreeArg1, class FreeArg2>
1623 void EmitterArg<TypeTuple<FreeArg1, FreeArg2> >::block(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> >& arg) {
1624  struct Pred {
1625  static bool pred(ListItem p, Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> > f) {
1626  return (p.f1 == f);
1627  }
1628  };
1629 
1630  typename std::list<ListItem>::iterator iter = emission_list.begin();
1631  for (;;) {
1632  iter = std::find_if(iter, emission_list.end(),
1633  std::bind2nd(std::ptr_fun(Pred::pred), arg));
1634  if (iter != emission_list.end()) {
1635  iter->blocked = true;
1636  ++iter;
1637  }
1638  else break;
1639  }
1640 }
1641 
1642 template <class FreeArg1, class FreeArg2>
1643 void EmitterArg<TypeTuple<FreeArg1, FreeArg2> >::unblock(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> >& arg) {
1644  struct Pred {
1645  static bool pred(ListItem p, Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2> > f) {
1646  return (p.f1 == f);
1647  }
1648  };
1649 
1650  typename std::list<ListItem>::iterator iter = emission_list.begin();
1651  for (;;) {
1652  iter = std::find_if(iter, emission_list.end(),
1653  std::bind2nd(std::ptr_fun(Pred::pred), arg));
1654  if (iter != emission_list.end()) {
1655  iter->blocked = false;
1656  ++iter;
1657  }
1658  else break;
1659  }
1660 }
1661 
1662 template <class FreeArg1, class FreeArg2, class FreeArg3>
1663 class EmitterArg <TypeTuple<FreeArg1, FreeArg2, FreeArg3> > {
1664  struct ListItem {
1665  Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > f1;
1666  Callback::Functor f2;
1667  bool blocked;
1668  ListItem(Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > f1_, Callback::Functor f2_):
1669  f1(f1_), f2(f2_), blocked(false) {}
1670  };
1671 
1672  std::list<ListItem> emission_list;
1673 
1674  void tracking_disconnect(Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >);
1675 
1676  EmitterArg(const EmitterArg&);
1677  EmitterArg& operator=(const EmitterArg&);
1678 public:
1679  friend class Releaser;
1680 
1681  void operator()(typename Cgu::Param<FreeArg1>::ParamType arg1,
1682  typename Cgu::Param<FreeArg2>::ParamType arg2,
1683  typename Cgu::Param<FreeArg3>::ParamType arg3) const {
1684  emit(arg1, arg2, arg3);
1685  }
1686  void emit(typename Cgu::Param<FreeArg1>::ParamType arg1,
1687  typename Cgu::Param<FreeArg2>::ParamType arg2,
1688  typename Cgu::Param<FreeArg3>::ParamType arg3) const;
1689 
1690  bool test_emit(typename Cgu::Param<FreeArg1>::ParamType arg1,
1691  typename Cgu::Param<FreeArg2>::ParamType arg2,
1692  typename Cgu::Param<FreeArg3>::ParamType arg3) const;
1693 
1694  Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > connect(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& f);
1695  Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > connect(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& f, Releaser& r);
1696  void disconnect(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& f);
1697 
1698  void block(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& f);
1699  void unblock(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& f);
1700 
1701  EmitterArg() {}
1702  ~EmitterArg();
1703 
1704 /* Only has effect if --with-glib-memory-slices-compat or
1705  * --with-glib-memory-slices-no-compat option picked */
1707 };
1708 
1709 template <class FreeArg1, class FreeArg2, class FreeArg3>
1710 EmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::~EmitterArg() {
1711 
1712  struct DisconnectReleaserItem {
1713  static void exec(const ListItem& l) {(l.f2)();}
1714  };
1715  std::for_each(emission_list.begin(), emission_list.end(),
1717 }
1718 
1719 template <class FreeArg1, class FreeArg2, class FreeArg3>
1720 void EmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::emit(typename Cgu::Param<FreeArg1>::ParamType arg1,
1721  typename Cgu::Param<FreeArg2>::ParamType arg2,
1722  typename Cgu::Param<FreeArg3>::ParamType arg3) const {
1723  std::list<ListItem> local_list = emission_list;
1724 
1725  typename std::list<ListItem>::const_iterator iter;
1726  for (iter = local_list.begin(); iter != local_list.end(); ++iter) {
1727  if (!iter->blocked) iter->f1(arg1, arg2, arg3);
1728  }
1729 }
1730 
1731 template <class FreeArg1, class FreeArg2, class FreeArg3>
1732 bool EmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::test_emit(typename Cgu::Param<FreeArg1>::ParamType arg1,
1733  typename Cgu::Param<FreeArg2>::ParamType arg2,
1734  typename Cgu::Param<FreeArg3>::ParamType arg3) const {
1735  if (emission_list.empty()) return false;
1736  emit(arg1, arg2, arg3);
1737  return true;
1738 }
1739 
1740 template <class FreeArg1, class FreeArg2, class FreeArg3>
1741 Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > EmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::connect(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& f1) {
1742  emission_list.push_back(ListItem(f1, Callback::Functor()));
1743  return f1;
1744 }
1745 
1746 template <class FreeArg1, class FreeArg2, class FreeArg3>
1747 Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > EmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::connect(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& f1, Releaser& r) {
1748  // In this method:
1749  // f1 is the functor we execute when we emit()
1750  // f2 is the functor we execute in our destructor if we are destroyed before the
1751  // remote object is
1752  // f3 is the functor the remote object executes in its Releaser if it is destroyed
1753  // before we are, or if Releaser::operator=() is called
1754 
1755  Callback::SafeFunctor f3(Callback::make_ref(*this, &EmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::tracking_disconnect, f1));
1756  Callback::Functor f2(Callback::make_ref(r, &Releaser::remove, f3));
1757  r.add(f3);
1758  try {
1759  emission_list.push_back(ListItem(f1, f2));
1760  }
1761  catch (...) {
1762  r.remove(f3);
1763  throw;
1764  }
1765  return f1;
1766 }
1767 
1768 template <class FreeArg1, class FreeArg2, class FreeArg3>
1769 void EmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::disconnect(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& arg) {
1770  struct Pred {
1771  static bool pred(ListItem p, Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > f) {
1772  return (p.f1 == f);
1773  }
1774  };
1775 
1776  typename std::list<ListItem>::iterator iter = emission_list.begin();
1777  for (;;) {
1778  iter = std::find_if(iter, emission_list.end(),
1779  std::bind2nd(std::ptr_fun(Pred::pred), arg));
1780  if (iter != emission_list.end()) {
1781  (iter->f2)();
1782  iter = emission_list.erase(iter);
1783  }
1784  else break;
1785  }
1786 }
1787 
1788 template <class FreeArg1, class FreeArg2, class FreeArg3>
1789 void EmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::tracking_disconnect(Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > arg) {
1790  struct Pred {
1791  static bool pred(ListItem p, Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > f) {
1792  return (p.f1 == f);
1793  }
1794  };
1795 
1796  typename std::list<ListItem>::iterator iter = emission_list.begin();
1797  for (;;) {
1798  iter = std::find_if(iter, emission_list.end(),
1799  std::bind2nd(std::ptr_fun(Pred::pred), arg));
1800  if (iter != emission_list.end()) {
1801  iter = emission_list.erase(iter);
1802  }
1803  else break;
1804  }
1805 }
1806 
1807 template <class FreeArg1, class FreeArg2, class FreeArg3>
1808 void EmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::block(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& arg) {
1809  struct Pred {
1810  static bool pred(ListItem p, Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > f) {
1811  return (p.f1 == f);
1812  }
1813  };
1814 
1815  typename std::list<ListItem>::iterator iter = emission_list.begin();
1816  for (;;) {
1817  iter = std::find_if(iter, emission_list.end(),
1818  std::bind2nd(std::ptr_fun(Pred::pred), arg));
1819  if (iter != emission_list.end()) {
1820  iter->blocked = true;
1821  ++iter;
1822  }
1823  else break;
1824  }
1825 }
1826 
1827 template <class FreeArg1, class FreeArg2, class FreeArg3>
1828 void EmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::unblock(const Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& arg) {
1829  struct Pred {
1830  static bool pred(ListItem p, Callback::FunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > f) {
1831  return (p.f1 == f);
1832  }
1833  };
1834 
1835  typename std::list<ListItem>::iterator iter = emission_list.begin();
1836  for (;;) {
1837  iter = std::find_if(iter, emission_list.end(),
1838  std::bind2nd(std::ptr_fun(Pred::pred), arg));
1839  if (iter != emission_list.end()) {
1840  iter->blocked = false;
1841  ++iter;
1842  }
1843  else break;
1844  }
1845 }
1846 
1847 /* SafeEmitterArg specialisations */
1848 
1849 template <>
1850 class SafeEmitterArg<void> {
1851  struct ListItem {
1853  Callback::SafeFunctorArg<int*> f2;
1854  bool blocked;
1855  ListItem(Callback::SafeFunctor f1_, Callback::SafeFunctorArg<int*> f2_):
1856  f1(f1_), f2(f2_), blocked(false) {}
1857  };
1858 
1859  std::list<ListItem> emission_list;
1860  mutable Thread::Mutex mutex;
1861 
1862  void tracking_disconnect(Callback::SafeFunctor);
1863 
1865  SafeEmitterArg& operator=(const SafeEmitterArg&);
1866 public:
1867  friend class Releaser;
1868 
1869  void operator()() const {emit();}
1870  void emit() const;
1871 
1872  bool test_emit() const;
1873 
1876  void disconnect(const Callback::SafeFunctor&);
1877 
1878  void block(const Callback::SafeFunctor&);
1879  void unblock(const Callback::SafeFunctor&);
1880 
1881  SafeEmitterArg() {}
1882  ~SafeEmitterArg();
1883 
1884 /* Only has effect if --with-glib-memory-slices-compat or
1885  * --with-glib-memory-slices-no-compat option picked */
1887 };
1888 
1889 template <class FreeArg1, class FreeArg2>
1890 class SafeEmitterArg <TypeTuple<FreeArg1, FreeArg2> > {
1891  struct ListItem {
1892  Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> > f1;
1893  Callback::SafeFunctorArg<int*> f2;
1894  bool blocked;
1895  ListItem(Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> > f1_, Callback::SafeFunctorArg<int*> f2_):
1896  f1(f1_), f2(f2_), blocked(false) {}
1897  };
1898 
1899  std::list<ListItem> emission_list;
1900  mutable Thread::Mutex mutex;
1901 
1902  void tracking_disconnect(Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> >);
1903 
1905  SafeEmitterArg& operator=(const SafeEmitterArg&);
1906 public:
1907  friend class Releaser;
1908 
1909  void operator()(typename Cgu::Param<FreeArg1>::ParamType arg1,
1910  typename Cgu::Param<FreeArg2>::ParamType arg2) const {
1911  emit(arg1, arg2);
1912  }
1913  void emit(typename Cgu::Param<FreeArg1>::ParamType arg1,
1914  typename Cgu::Param<FreeArg2>::ParamType arg2) const;
1915 
1916  bool test_emit(typename Cgu::Param<FreeArg1>::ParamType arg1,
1917  typename Cgu::Param<FreeArg2>::ParamType arg2) const;
1918 
1919  Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> > connect(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> >& f);
1920  Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> > connect(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> >& f, Releaser& r);
1921  void disconnect(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> >& f);
1922 
1923  void block(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> >& f);
1924  void unblock(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> >& f);
1925 
1926  SafeEmitterArg() {}
1927  ~SafeEmitterArg();
1928 
1929 /* Only has effect if --with-glib-memory-slices-compat or
1930  * --with-glib-memory-slices-no-compat option picked */
1932 };
1933 
1934 template <class FreeArg1, class FreeArg2>
1935 SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2> >::~SafeEmitterArg() {
1936  Thread::Mutex::Lock lock(mutex);
1937  while (!emission_list.empty()) {
1938  typename std::list<ListItem>::iterator iter = emission_list.begin();
1939  int result = 0;
1940  (iter->f2)(&result);
1941  if (!result) {
1942  emission_list.erase(iter);
1943  }
1944  else {
1945  mutex.unlock();
1946 #ifdef CGU_USE_SCHED_YIELD
1947  sched_yield();
1948 #else
1949  usleep(10);
1950 #endif
1951  mutex.lock();
1952  }
1953  }
1954 }
1955 
1956 template <class FreeArg1, class FreeArg2>
1957 void SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2> >::emit(typename Cgu::Param<FreeArg1>::ParamType arg1,
1958  typename Cgu::Param<FreeArg2>::ParamType arg2) const {
1959  std::list<ListItem> local_list;
1960  {
1961  Thread::Mutex::Lock lock(mutex);
1962  local_list = emission_list;
1963  }
1964 
1965  typename std::list<ListItem>::const_iterator iter;
1966  for (iter = local_list.begin(); iter != local_list.end(); ++iter) {
1967  if (!iter->blocked) iter->f1(arg1, arg2);
1968  }
1969 }
1970 
1971 template <class FreeArg1, class FreeArg2>
1972 bool SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2> >::test_emit(typename Cgu::Param<FreeArg1>::ParamType arg1,
1973  typename Cgu::Param<FreeArg2>::ParamType arg2) const {
1974  std::list<ListItem> local_list;
1975  {
1976  Thread::Mutex::Lock lock(mutex);
1977  if (emission_list.empty()) return false;
1978  local_list = emission_list;
1979  }
1980 
1981  typename std::list<ListItem>::const_iterator iter;
1982  for (iter = local_list.begin(); iter != local_list.end(); ++iter) {
1983  if (!iter->blocked) iter->f1(arg1, arg2);
1984  }
1985  return true;
1986 }
1987 
1988 template <class FreeArg1, class FreeArg2>
1989 Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> > SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2> >::connect(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> >& f1) {
1990  std::list<ListItem> tmp;
1991  tmp.push_back(ListItem(f1, Callback::SafeFunctorArg<int*>()));
1992  Thread::Mutex::Lock lock(mutex);
1993  emission_list.splice(emission_list.end(), tmp);
1994  return f1;
1995 }
1996 
1997 template <class FreeArg1, class FreeArg2>
1998 Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> > SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2> >::connect(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> >& f1, Releaser& r) {
1999  // In this method:
2000  // f1 is the functor we execute when we emit()
2001  // f2 is the functor we execute in our destructor if we are destroyed before the
2002  // remote object is
2003  // f3 is the functor the remote object executes in its Releaser if it is destroyed
2004  // before we are, or if Releaser::operator=() is called
2005 
2006  Callback::SafeFunctor f3(Callback::make_ref(*this, &SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2> >::tracking_disconnect, f1));
2007  Callback::SafeFunctorArg<int*> f2(Callback::make_ref(r, &Releaser::try_remove, f3));
2008  r.add(f3);
2009  try {
2010  std::list<ListItem> tmp;
2011  tmp.push_back(ListItem(f1, f2));
2012  Thread::Mutex::Lock lock(mutex);
2013  emission_list.splice(emission_list.end(), tmp);
2014  }
2015  catch (...) {
2016  r.remove(f3);
2017  throw;
2018  }
2019  return f1;
2020 }
2021 
2022 template <class FreeArg1, class FreeArg2>
2023 void SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2> >::disconnect(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> >& arg) {
2024  struct Pred {
2025  static bool pred(ListItem p, Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> > f) {
2026  return (p.f1 == f);
2027  }
2028  };
2029 
2030  Thread::Mutex::Lock lock(mutex);
2031  typename std::list<ListItem>::iterator iter = emission_list.begin();
2032  for(;;) {
2033  iter = std::find_if(iter, emission_list.end(),
2034  std::bind2nd(std::ptr_fun(Pred::pred), arg));
2035  if (iter != emission_list.end()) {
2036  int result = 0;
2037  (iter->f2)(&result);
2038  if (!result) {
2039  iter = emission_list.erase(iter);
2040  }
2041  else {
2042  mutex.unlock();
2043 #ifdef CGU_USE_SCHED_YIELD
2044  sched_yield();
2045 #else
2046  usleep(10);
2047 #endif
2048  mutex.lock();
2049  iter = emission_list.begin();
2050  }
2051  }
2052  else break;
2053  }
2054 }
2055 
2056 template <class FreeArg1, class FreeArg2>
2057 void SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2> >::tracking_disconnect(Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> > arg) {
2058  struct Pred {
2059  static bool pred(ListItem p, Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> > f) {
2060  return (p.f1 == f);
2061  }
2062  };
2063 
2064  Thread::Mutex::Lock lock(mutex);
2065  typename std::list<ListItem>::iterator iter = emission_list.begin();
2066  for (;;) {
2067  iter = std::find_if(iter, emission_list.end(),
2068  std::bind2nd(std::ptr_fun(Pred::pred), arg));
2069  if (iter != emission_list.end()) {
2070  iter = emission_list.erase(iter);
2071  }
2072  else break;
2073  }
2074 }
2075 
2076 template <class FreeArg1, class FreeArg2>
2077 void SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2> >::block(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> >& arg) {
2078  struct Pred {
2079  static bool pred(ListItem p, Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> > f) {
2080  return (p.f1 == f);
2081  }
2082  };
2083 
2084  Thread::Mutex::Lock lock(mutex);
2085  typename std::list<ListItem>::iterator iter = emission_list.begin();
2086  for (;;) {
2087  iter = std::find_if(iter, emission_list.end(),
2088  std::bind2nd(std::ptr_fun(Pred::pred), arg));
2089  if (iter != emission_list.end()) {
2090  iter->blocked = true;
2091  ++iter;
2092  }
2093  else break;
2094  }
2095 }
2096 
2097 template <class FreeArg1, class FreeArg2>
2098 void SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2> >::unblock(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> >& arg) {
2099  struct Pred {
2100  static bool pred(ListItem p, Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2> > f) {
2101  return (p.f1 == f);
2102  }
2103  };
2104 
2105  Thread::Mutex::Lock lock(mutex);
2106  typename std::list<ListItem>::iterator iter = emission_list.begin();
2107  for (;;) {
2108  iter = std::find_if(iter, emission_list.end(),
2109  std::bind2nd(std::ptr_fun(Pred::pred), arg));
2110  if (iter != emission_list.end()) {
2111  iter->blocked = false;
2112  ++iter;
2113  }
2114  else break;
2115  }
2116 }
2117 
2118 template <class FreeArg1, class FreeArg2, class FreeArg3>
2119 class SafeEmitterArg <TypeTuple<FreeArg1, FreeArg2, FreeArg3> > {
2120  struct ListItem {
2121  Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > f1;
2122  Callback::SafeFunctorArg<int*> f2;
2123  bool blocked;
2124  ListItem(Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > f1_, Callback::SafeFunctorArg<int*> f2_):
2125  f1(f1_), f2(f2_), blocked(false) {}
2126  };
2127 
2128  std::list<ListItem> emission_list;
2129  mutable Thread::Mutex mutex;
2130 
2131  void tracking_disconnect(Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >);
2132 
2134  SafeEmitterArg& operator=(const SafeEmitterArg&);
2135 public:
2136  friend class Releaser;
2137 
2138  void operator()(typename Cgu::Param<FreeArg1>::ParamType arg1,
2139  typename Cgu::Param<FreeArg2>::ParamType arg2,
2140  typename Cgu::Param<FreeArg3>::ParamType arg3) const {
2141  emit(arg1, arg2, arg3);
2142  }
2143  void emit(typename Cgu::Param<FreeArg1>::ParamType arg1,
2144  typename Cgu::Param<FreeArg2>::ParamType arg2,
2145  typename Cgu::Param<FreeArg3>::ParamType arg3) const;
2146 
2147  bool test_emit(typename Cgu::Param<FreeArg1>::ParamType arg1,
2148  typename Cgu::Param<FreeArg2>::ParamType arg2,
2149  typename Cgu::Param<FreeArg3>::ParamType arg3) const;
2150 
2151  Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > connect(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& f);
2152  Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > connect(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& f, Releaser& r);
2153  void disconnect(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& f);
2154 
2155  void block(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& f);
2156  void unblock(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& f);
2157 
2158  SafeEmitterArg() {}
2159  ~SafeEmitterArg();
2160 
2161 /* Only has effect if --with-glib-memory-slices-compat or
2162  * --with-glib-memory-slices-no-compat option picked */
2164 };
2165 
2166 template <class FreeArg1, class FreeArg2, class FreeArg3>
2167 SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::~SafeEmitterArg() {
2168  Thread::Mutex::Lock lock(mutex);
2169  while (!emission_list.empty()) {
2170  typename std::list<ListItem>::iterator iter = emission_list.begin();
2171  int result = 0;
2172  (iter->f2)(&result);
2173  if (!result) {
2174  emission_list.erase(iter);
2175  }
2176  else {
2177  mutex.unlock();
2178 #ifdef CGU_USE_SCHED_YIELD
2179  sched_yield();
2180 #else
2181  usleep(10);
2182 #endif
2183  mutex.lock();
2184  }
2185  }
2186 }
2187 
2188 template <class FreeArg1, class FreeArg2, class FreeArg3>
2189 void SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::emit(typename Cgu::Param<FreeArg1>::ParamType arg1,
2190  typename Cgu::Param<FreeArg2>::ParamType arg2,
2191  typename Cgu::Param<FreeArg3>::ParamType arg3) const {
2192  std::list<ListItem> local_list;
2193  {
2194  Thread::Mutex::Lock lock(mutex);
2195  local_list = emission_list;
2196  }
2197 
2198  typename std::list<ListItem>::const_iterator iter;
2199  for (iter = local_list.begin(); iter != local_list.end(); ++iter) {
2200  if (!iter->blocked) iter->f1(arg1, arg2, arg3);
2201  }
2202 }
2203 
2204 template <class FreeArg1, class FreeArg2, class FreeArg3>
2205 bool SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::test_emit(typename Cgu::Param<FreeArg1>::ParamType arg1,
2206  typename Cgu::Param<FreeArg2>::ParamType arg2,
2207  typename Cgu::Param<FreeArg3>::ParamType arg3) const {
2208  std::list<ListItem> local_list;
2209  {
2210  Thread::Mutex::Lock lock(mutex);
2211  if (emission_list.empty()) return false;
2212  local_list = emission_list;
2213  }
2214 
2215  typename std::list<ListItem>::const_iterator iter;
2216  for (iter = local_list.begin(); iter != local_list.end(); ++iter) {
2217  if (!iter->blocked) iter->f1(arg1, arg2, arg3);
2218  }
2219  return true;
2220 }
2221 
2222 template <class FreeArg1, class FreeArg2, class FreeArg3>
2223 Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::connect(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& f1) {
2224  std::list<ListItem> tmp;
2225  tmp.push_back(ListItem(f1, Callback::SafeFunctorArg<int*>()));
2226  Thread::Mutex::Lock lock(mutex);
2227  emission_list.splice(emission_list.end(), tmp);
2228  return f1;
2229 }
2230 
2231 template <class FreeArg1, class FreeArg2, class FreeArg3>
2232 Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::connect(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& f1, Releaser& r) {
2233  // In this method:
2234  // f1 is the functor we execute when we emit()
2235  // f2 is the functor we execute in our destructor if we are destroyed before the
2236  // remote object is
2237  // f3 is the functor the remote object executes in its Releaser if it is destroyed
2238  // before we are, or if Releaser::operator=() is called
2239 
2240  Callback::SafeFunctor f3(Callback::make_ref(*this, &SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::tracking_disconnect, f1));
2241  Callback::SafeFunctorArg<int*> f2(Callback::make_ref(r, &Releaser::try_remove, f3));
2242  r.add(f3);
2243  try {
2244  std::list<ListItem> tmp;
2245  tmp.push_back(ListItem(f1, f2));
2246  Thread::Mutex::Lock lock(mutex);
2247  emission_list.splice(emission_list.end(), tmp);
2248  }
2249  catch (...) {
2250  r.remove(f3);
2251  throw;
2252  }
2253  return f1;
2254 }
2255 
2256 template <class FreeArg1, class FreeArg2, class FreeArg3>
2257 void SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::disconnect(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& arg) {
2258  struct Pred {
2259  static bool pred(ListItem p, Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > f) {
2260  return (p.f1 == f);
2261  }
2262  };
2263 
2264  Thread::Mutex::Lock lock(mutex);
2265  typename std::list<ListItem>::iterator iter = emission_list.begin();
2266  for(;;) {
2267  iter = std::find_if(iter, emission_list.end(),
2268  std::bind2nd(std::ptr_fun(Pred::pred), arg));
2269  if (iter != emission_list.end()) {
2270  int result = 0;
2271  (iter->f2)(&result);
2272  if (!result) {
2273  iter = emission_list.erase(iter);
2274  }
2275  else {
2276  mutex.unlock();
2277 #ifdef CGU_USE_SCHED_YIELD
2278  sched_yield();
2279 #else
2280  usleep(10);
2281 #endif
2282  mutex.lock();
2283  iter = emission_list.begin();
2284  }
2285  }
2286  else break;
2287  }
2288 }
2289 
2290 template <class FreeArg1, class FreeArg2, class FreeArg3>
2291 void SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::tracking_disconnect(Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > arg) {
2292  struct Pred {
2293  static bool pred(ListItem p, Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > f) {
2294  return (p.f1 == f);
2295  }
2296  };
2297 
2298  Thread::Mutex::Lock lock(mutex);
2299  typename std::list<ListItem>::iterator iter = emission_list.begin();
2300  for (;;) {
2301  iter = std::find_if(iter, emission_list.end(),
2302  std::bind2nd(std::ptr_fun(Pred::pred), arg));
2303  if (iter != emission_list.end()) {
2304  iter = emission_list.erase(iter);
2305  }
2306  else break;
2307  }
2308 }
2309 
2310 template <class FreeArg1, class FreeArg2, class FreeArg3>
2311 void SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::block(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& arg) {
2312  struct Pred {
2313  static bool pred(ListItem p, Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > f) {
2314  return (p.f1 == f);
2315  }
2316  };
2317 
2318  Thread::Mutex::Lock lock(mutex);
2319  typename std::list<ListItem>::iterator iter = emission_list.begin();
2320  for (;;) {
2321  iter = std::find_if(iter, emission_list.end(),
2322  std::bind2nd(std::ptr_fun(Pred::pred), arg));
2323  if (iter != emission_list.end()) {
2324  iter->blocked = true;
2325  ++iter;
2326  }
2327  else break;
2328  }
2329 }
2330 
2331 template <class FreeArg1, class FreeArg2, class FreeArg3>
2332 void SafeEmitterArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >::unblock(const Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> >& arg) {
2333  struct Pred {
2334  static bool pred(ListItem p, Callback::SafeFunctorArg<TypeTuple<FreeArg1, FreeArg2, FreeArg3> > f) {
2335  return (p.f1 == f);
2336  }
2337  };
2338 
2339  Thread::Mutex::Lock lock(mutex);
2340  typename std::list<ListItem>::iterator iter = emission_list.begin();
2341  for (;;) {
2342  iter = std::find_if(iter, emission_list.end(),
2343  std::bind2nd(std::ptr_fun(Pred::pred), arg));
2344  if (iter != emission_list.end()) {
2345  iter->blocked = false;
2346  ++iter;
2347  }
2348  else break;
2349  }
2350 }
2351 
2352 #endif // DOXYGEN_PARSING
2353 
2354 } // namespace Cgu
2355 
2356 #endif // EMITTER_H
Cgu::Param
Struct for automatic typing of parameter arguments for template functions.
Definition: param.h:79
Cgu
Definition: application.h:45
Cgu::SafeEmitterArg::~SafeEmitterArg
~SafeEmitterArg()
Definition: emitter.h:1142
Cgu::Callback::Functor
FunctorArg< void > Functor
Definition: callback.h:1078
Cgu::SafeEmitterArg::unblock
void unblock(const Callback::SafeFunctorArg< FreeArg > &f)
Definition: emitter.h:1401
Cgu::EmitterArg::test_emit
bool test_emit(typename Cgu::Param< FreeArg >::ParamType arg) const
Definition: emitter.h:741
Cgu::SafeEmitterArg::block
void block(const Callback::SafeFunctorArg< FreeArg > &f)
Definition: emitter.h:1376
Cgu::EmitterArg::disconnect
void disconnect(const Callback::FunctorArg< FreeArg > &f)
Definition: emitter.h:776
callback.h
This file provides classes encapsulating callbacks.
Cgu::EmitterArg::unblock
void unblock(const Callback::FunctorArg< FreeArg > &f)
Definition: emitter.h:852
Cgu::Callback::make_ref
Callback * make_ref(T &t, void(T::*func)())
Definition: callback.h:2414
Cgu::SafeEmitterArg::SafeEmitterArg
SafeEmitterArg()
Definition: emitter.h:1124
Cgu::SafeEmitterArg::connect
Callback::SafeFunctorArg< FreeArg > connect(const Callback::SafeFunctorArg< FreeArg > &f)
Cgu::Releaser::Releaser
Releaser()
Definition: emitter.h:432
Cgu::Emitter
EmitterArg< void > Emitter
Definition: emitter.h:343
Cgu::Extension::exec
Ret exec(const std::string &preamble, const std::string &file, Ret(*translator)(SCM))
Definition: extension.h:1698
Cgu::EmitterArg::Releaser
friend class Releaser
Definition: emitter.h:535
Cgu::Callback::SafeFunctor
SafeFunctorArg< void > SafeFunctor
Definition: callback.h:1080
Cgu::Releaser::~Releaser
~Releaser()
param.h
Cgu::SafeEmitterArg::operator()
void operator()(typename Cgu::Param< FreeArg >::ParamType arg) const
Definition: emitter.h:979
Cgu::EmitterArg::EmitterArg
EmitterArg()
Definition: emitter.h:676
Cgu::Releaser::operator=
Releaser & operator=(const Releaser &r)
Cgu::SafeEmitter
SafeEmitterArg< void > SafeEmitter
Definition: emitter.h:345
Cgu::SafeEmitterArg
A thread-safe class to execute callbacks connected to it, with provision for automatic disconnection.
Definition: emitter.h:343
Cgu::EmitterArg::~EmitterArg
~EmitterArg()
Definition: emitter.h:692
Cgu::Callback::SafeFunctorArg
Functor class holding a Callback::CallbackArg object, with thread-safe reference count.
Definition: callback.h:1078
Cgu::Thread::Mutex::Lock
A scoped locking class for exception safe Mutex locking.
Definition: mutex.h:192
CGU_GLIB_MEMORY_SLICES_FUNCS
#define CGU_GLIB_MEMORY_SLICES_FUNCS
Definition: cgu_config.h:84
Cgu::EmitterArg::operator()
void operator()(typename Cgu::Param< FreeArg >::ParamType arg) const
Definition: emitter.h:551
Cgu::EmitterArg::connect
Callback::FunctorArg< FreeArg > connect(const Callback::FunctorArg< FreeArg > &f)
mutex.h
Provides wrapper classes for pthread mutexes and condition variables, and scoped locking classes for ...
Cgu::EmitterArg::block
void block(const Callback::FunctorArg< FreeArg > &f)
Definition: emitter.h:828
Cgu::EmitterArg
A class to execute callbacks connected to it, with provision for automatic disconnection.
Definition: emitter.h:342
Cgu::Releaser::Releaser
Releaser(const Releaser &r)
Definition: emitter.h:420
Cgu::Callback::FunctorArg
Functor class holding a Callback::CallbackArg object.
Definition: callback.h:1077
Cgu::Releaser
A class used for tracking EmitterArg and SafeEmitterArg connections.
Definition: emitter.h:368
Cgu::SafeEmitterArg::test_emit
bool test_emit(typename Cgu::Param< FreeArg >::ParamType arg) const
Definition: emitter.h:1247
Cgu::EmitterArg::emit
void emit(typename Cgu::Param< FreeArg >::ParamType arg) const
Definition: emitter.h:702
Cgu::SafeEmitterArg::disconnect
void disconnect(const Callback::SafeFunctorArg< FreeArg > &f)
Definition: emitter.h:1307
Cgu::SafeEmitterArg::emit
void emit(typename Cgu::Param< FreeArg >::ParamType arg) const
Definition: emitter.h:1171
Cgu::Thread::Mutex
A wrapper class for pthread mutexes.
Definition: mutex.h:109
Cgu::SafeEmitterArg::Releaser
friend class Releaser
Definition: emitter.h:961
cgu_config.h