1 #ifndef _GLIBMM_DISPATCHER_H 2 #define _GLIBMM_DISPATCHER_H 3 4 /* Copyright 2002 The gtkmm Development Team 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include <sigc++/sigc++.h> 21 #include <glibmm/main.h> 22 23 namespace Glib 24 { 25 26 #ifndef DOXYGEN_SHOULD_SKIP_THIS 27 class DispatchNotifier; 28 #endif 29 30 /** Signal class for inter-thread communication. 31 * @ingroup Threads 32 * Glib::Dispatcher works similar to sigc::signal<void>. But unlike normal 33 * signals, the notification happens asynchronously through a pipe. This is 34 * a simple and efficient way of communicating between threads, and especially 35 * useful in a thread model with a single GUI thread. 36 * 37 * No mutex locking is involved, apart from the operating system's internal 38 * I/O locking. That implies some usage rules: 39 * 40 * @li Only one thread may connect to the signal and receive notification, but 41 * multiple senders are allowed even without locking. 42 * @li The GLib main loop must run in the receiving thread (this will be the 43 * GUI thread usually). 44 * @li The Dispatcher object must be instantiated by the receiver thread. 45 * @li The Dispatcher object should be instantiated before creating any of the 46 * sender threads, if you want to avoid extra locking. 47 * @li The Dispatcher object must be deleted by the receiver thread. 48 * @li All Dispatcher objects instantiated by the same receiver thread must 49 * use the same main context. 50 * 51 * Notes about performance: 52 * 53 * @li After instantiation, Glib::Dispatcher will never lock any mutexes on its 54 * own. The interaction with the GLib main loop might involve locking on the 55 * @em receiver side. The @em sender side, however, is guaranteed not to lock, 56 * except for internal locking in the <tt>%write()</tt> system call. 57 * @li All Dispatcher instances of a receiver thread share the same pipe. That 58 * is, if you use Glib::Dispatcher only to notify the GUI thread, only one pipe 59 * is created no matter how many Dispatcher objects you have. 60 * 61 * Using Glib::Dispatcher on Windows: 62 * 63 * Glib::Dispatcher also works on win32-based systems. Unfortunately though, 64 * the implementation cannot use a pipe on win32 and therefore does have to 65 * lock a mutex on emission, too. However, the impact on performance is 66 * likely minor and the notification still happens asynchronously. Apart 67 * from the additional lock the behavior matches the Unix implementation. 68 */ 69 class GLIBMM_API Dispatcher 70 { 71 public: 72 /** Create new Dispatcher instance using the default main context. 73 * @throw Glib::FileError 74 */ 75 Dispatcher(); 76 77 // noncopyable 78 Dispatcher(const Dispatcher&) = delete; 79 Dispatcher& operator=(const Dispatcher&) = delete; 80 81 /** Create new Dispatcher instance using an arbitrary main context. 82 * @throw Glib::FileError 83 */ 84 explicit Dispatcher(const Glib::RefPtr<MainContext>& context); 85 ~Dispatcher() noexcept; 86 87 void emit(); 88 void operator()(); 89 90 sigc::connection connect(const sigc::slot<void>& slot); 91 /** @newin{2,48} 92 */ 93 sigc::connection connect(sigc::slot<void>&& slot); 94 95 private: 96 sigc::signal<void> signal_; 97 DispatchNotifier* notifier_; 98 99 #ifndef DOXYGEN_SHOULD_SKIP_THIS 100 friend class Glib::DispatchNotifier; 101 #endif 102 }; 103 104 /*! A Glib::Dispatcher example. 105 * @example thread/dispatcher.cc 106 */ 107 108 } // namespace Glib 109 110 #endif /* _GLIBMM_DISPATCHER_H */ 111