1 #ifndef _GLIBMM_MAIN_H
2 #define _GLIBMM_MAIN_H
3 
4 /* Copyright (C) 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 <glibmmconfig.h>
21 #include <glibmm/refptr.h>
22 #include <glibmm/timeval.h>
23 #include <glibmm/priorities.h>
24 #include <glibmm/iochannel.h>
25 #include <sigc++/sigc++.h>
26 #include <vector>
27 #include <cstddef>
28 
29 namespace Glib
30 {
31 
32 #ifndef GLIBMM_DISABLE_DEPRECATED
33 class GLIBMM_API Cond;
34 class GLIBMM_API Mutex;
35 
36 namespace Threads
37 {
38 class GLIBMM_API Cond;
39 class GLIBMM_API Mutex;
40 }
41 #endif // GLIBMM_DISABLE_DEPRECATED
42 
43 /** @defgroup MainLoop The Main Event Loop
44  * Manages all available sources of events.
45  * @{
46  */
47 class GLIBMM_API PollFD
48 {
49 public:
50   using fd_t = decltype(GPollFD::fd);
51 
52   PollFD();
53   explicit PollFD(fd_t fd);
54   PollFD(fd_t fd, IOCondition events);
55 
set_fd(fd_t fd)56   void set_fd(fd_t fd) { gobject_.fd = fd; }
get_fd()57   fd_t get_fd() const { return gobject_.fd; }
58 
set_events(IOCondition events)59   void set_events(IOCondition events) { gobject_.events = events; }
get_events()60   IOCondition get_events() const { return static_cast<IOCondition>(gobject_.events); }
61 
set_revents(IOCondition revents)62   void set_revents(IOCondition revents) { gobject_.revents = revents; }
get_revents()63   IOCondition get_revents() const { return static_cast<IOCondition>(gobject_.revents); }
64 
gobj()65   GPollFD* gobj() { return &gobject_; }
gobj()66   const GPollFD* gobj() const { return &gobject_; }
67 
68 private:
69   GPollFD gobject_;
70 };
71 
72 // Concerning SignalTimeout::connect_once(), SignalTimeout::connect_seconds_once()
73 // and SignalIdle::connect_once():
74 // See https://bugzilla.gnome.org/show_bug.cgi?id=396963 and
75 // http://bugzilla.gnome.org/show_bug.cgi?id=512348 about the sigc::trackable issue.
76 // It's recommended to replace sigc::slot<void>& by std::function<void()>& in
77 // Threads::Thread::create() and ThreadPool::push() at the next ABI break.
78 // Such a replacement would be a mixed blessing in SignalTimeout and SignalIdle.
79 // In a single-threaded program auto-disconnection of trackable slots is safe
80 // and can be useful.
81 
82 class GLIBMM_API SignalTimeout
83 {
84 public:
85 #ifndef DOXYGEN_SHOULD_SKIP_THIS
86   explicit inline SignalTimeout(GMainContext* context);
87 #endif
88 
89   /** Connects a timeout handler.
90    *
91    * Note that timeout functions may be delayed, due to the processing of other
92    * event sources. Thus they should not be relied on for precise timing.
93    * After each call to the timeout function, the time of the next
94    * timeout is recalculated based on the current time and the given interval
95    * (it does not try to 'catch up' time lost in delays).
96    *
97    * If you want to have a timer in the "seconds" range and do not care
98    * about the exact time of the first call of the timer, use the
99    * connect_seconds() function; this function allows for more
100    * optimizations and more efficient system power usage.
101    *
102    * @code
103    * bool timeout_handler() { ... }
104    * Glib::signal_timeout().connect(sigc::ptr_fun(&timeout_handler), 1000);
105    * @endcode
106    * is equivalent to:
107    * @code
108    * bool timeout_handler() { ... }
109    * const auto timeout_source = Glib::TimeoutSource::create(1000);
110    * timeout_source->connect(sigc::ptr_fun(&timeout_handler));
111    * timeout_source->attach(Glib::MainContext::get_default());
112    * @endcode
113    *
114    * This method is not thread-safe. You should call it, or manipulate the
115    * returned sigc::connection object, only from the thread where the SignalTimeout
116    * object's MainContext runs.
117    *
118    * @param slot A slot to call when @a interval has elapsed.
119    * If <tt>timeout_handler()</tt> returns <tt>false</tt> the handler is disconnected.
120    * @param interval The timeout in milliseconds.
121    * @param priority The priority of the new event source.
122    * @return A connection handle, which can be used to disconnect the handler.
123    */
124   sigc::connection connect(
125     const sigc::slot<bool>& slot, unsigned int interval, int priority = PRIORITY_DEFAULT);
126 
127   /** Connects a timeout handler that runs only once.
128    * This method takes a function pointer to a function with a void return
129    * and no parameters. After running once it is not called again.
130    *
131    * Because sigc::trackable is not thread-safe, if the slot represents a
132    * non-static method of a class deriving from sigc::trackable, and the slot is
133    * created by sigc::mem_fun(), connect_once() should only be called from
134    * the thread where the SignalTimeout object's MainContext runs. You can use,
135    * say, boost::bind() or, in C++11, std::bind() or a C++11 lambda expression
136    * instead of sigc::mem_fun().
137    *
138    * @see connect()
139    * @param slot A slot to call when @a interval has elapsed. For example:
140    * @code
141    * void on_timeout_once()
142    * @endcode
143    * @param interval The timeout in milliseconds.
144    * @param priority The priority of the new event source.
145    */
146   void connect_once(
147     const sigc::slot<void>& slot, unsigned int interval, int priority = PRIORITY_DEFAULT);
148 
149   /** Connects a timeout handler with whole second granularity.
150    *
151    * Unlike connect(), this operates at whole second granularity.
152    * The initial starting point of the timer is determined by the implementation
153    * and the implementation is expected to group multiple timers together so that
154    * they fire all at the same time.
155    *
156    * To allow this grouping, the @a interval to the first timer is rounded
157    * and can deviate up to one second from the specified interval.
158    * Subsequent timer iterations will generally run at the specified interval.
159    *
160    * @code
161    * bool timeout_handler() { ... }
162    * Glib::signal_timeout().connect_seconds(sigc::ptr_fun(&timeout_handler), 5);
163    * @endcode
164    * is equivalent to:
165    * @code
166    * bool timeout_handler() { ... }
167    * const auto timeout_source = Glib::TimeoutSource::create(5000);
168    * timeout_source->connect(sigc::ptr_fun(&timeout_handler));
169    * timeout_source->attach(Glib::MainContext::get_default());
170    * @endcode
171    *
172    * This method is not thread-safe. You should call it, or manipulate the
173    * returned sigc::connection object, only from the thread where the SignalTimeout
174    * object's MainContext runs.
175    *
176    * @param slot A slot to call when @a interval has elapsed.
177    * If <tt>timeout_handler()</tt> returns <tt>false</tt> the handler is disconnected.
178    * @param interval The timeout in seconds.
179    * @param priority The priority of the new event source.
180    * @return A connection handle, which can be used to disconnect the handler.
181    *
182    * @newin{2,14}
183    */
184   sigc::connection connect_seconds(
185     const sigc::slot<bool>& slot, unsigned int interval, int priority = PRIORITY_DEFAULT);
186 
187   /** Connects a timeout handler that runs only once with whole second
188    *  granularity.
189    *
190    * This method takes a function pointer to a function with a void return
191    * and no parameters. After running once it is not called again.
192    *
193    * Because sigc::trackable is not thread-safe, if the slot represents a
194    * non-static method of a class deriving from sigc::trackable, and the slot is
195    * created by sigc::mem_fun(), connect_seconds_once() should only be called from
196    * the thread where the SignalTimeout object's MainContext runs. You can use,
197    * say, boost::bind() or, in C++11, std::bind() or a C++11 lambda expression
198    * instead of sigc::mem_fun().
199    *
200    * @see connect_seconds()
201    * @param slot A slot to call when @a interval has elapsed. For example:
202    * @code
203    * void on_timeout_once()
204    * @endcode
205    * @param interval The timeout in seconds.
206    * @param priority The priority of the new event source.
207    */
208   void connect_seconds_once(
209     const sigc::slot<void>& slot, unsigned int interval, int priority = PRIORITY_DEFAULT);
210 
211 private:
212   GMainContext* context_;
213 
214   // no copy assignment
215   SignalTimeout& operator=(const SignalTimeout&);
216 };
217 
218 class GLIBMM_API SignalIdle
219 {
220 public:
221 #ifndef DOXYGEN_SHOULD_SKIP_THIS
222   explicit inline SignalIdle(GMainContext* context);
223 #endif
224 
225   /** Connects an idle handler.
226    * @code
227    * bool idle_handler() { ... }
228    * Glib::signal_idle().connect(sigc::ptr_fun(&idle_handler));
229    * @endcode
230    * is equivalent to:
231    * @code
232    * bool idle_handler() { ... }
233    * const auto idle_source = Glib::IdleSource::create();
234    * idle_source->connect(sigc::ptr_fun(&idle_handler));
235    * idle_source->attach(Glib::MainContext::get_default());
236    * @endcode
237    *
238    * This method is not thread-safe. You should call it, or manipulate the
239    * returned sigc::connection object, only from the thread where the SignalIdle
240    * object's MainContext runs.
241    *
242    * @param slot A slot to call when the main loop is idle.
243    * If <tt>idle_handler()</tt> returns <tt>false</tt> the handler is disconnected.
244    * @param priority The priority of the new event source.
245    * @return A connection handle, which can be used to disconnect the handler.
246    */
247   sigc::connection connect(const sigc::slot<bool>& slot, int priority = PRIORITY_DEFAULT_IDLE);
248 
249   /** Connects an idle handler that runs only once.
250    * This method takes a function pointer to a function with a void return
251    * and no parameters. After running once it is not called again.
252    *
253    * Because sigc::trackable is not thread-safe, if the slot represents a
254    * non-static method of a class deriving from sigc::trackable, and the slot is
255    * created by sigc::mem_fun(), connect_once() should only be called from
256    * the thread where the SignalIdle object's MainContext runs. You can use,
257    * say, boost::bind() or, in C++11, std::bind() or a C++11 lambda expression
258    * instead of sigc::mem_fun().
259    *
260    * @see connect()
261    * @param slot A slot to call when the main loop is idle. For example:
262    * @code
263    * void on_idle_once()
264    * @endcode
265    * @param priority The priority of the new event source.
266    */
267   void connect_once(const sigc::slot<void>& slot, int priority = PRIORITY_DEFAULT_IDLE);
268 
269 private:
270   GMainContext* context_;
271 
272   // no copy assignment
273   SignalIdle& operator=(const SignalIdle&);
274 };
275 
276 class GLIBMM_API SignalIO
277 {
278 public:
279 #ifndef DOXYGEN_SHOULD_SKIP_THIS
280   explicit inline SignalIO(GMainContext* context);
281 #endif
282 
283   /** Connects an I/O handler that watches a file descriptor.
284    * @code
285    * bool io_handler(Glib::IOCondition io_condition) { ... }
286    * Glib::signal_io().connect(sigc::ptr_fun(&io_handler), fd, Glib::IO_IN | Glib::IO_HUP);
287    * @endcode
288    * is equivalent to:
289    * @code
290    * bool io_handler(Glib::IOCondition io_condition) { ... }
291    * const auto io_source = Glib::IOSource::create(fd, Glib::IO_IN | Glib::IO_HUP);
292    * io_source->connect(sigc::ptr_fun(&io_handler));
293    * io_source->attach(Glib::MainContext::get_default());
294    * @endcode
295    *
296    * This method is not thread-safe. You should call it, or manipulate the
297    * returned sigc::connection object, only from the thread where the SignalIO
298    * object's MainContext runs.
299    *
300    * @param slot A slot to call when polling @a fd results in an event that matches @a condition.
301    * The event will be passed as a parameter to @a slot.
302    * If <tt>io_handler()</tt> returns <tt>false</tt> the handler is disconnected.
303    * @param fd The file descriptor (or a @c HANDLE on Win32 systems) to watch.
304    * @param condition The conditions to watch for.
305    * @param priority The priority of the new event source.
306    * @return A connection handle, which can be used to disconnect the handler.
307    */
308   sigc::connection connect(const sigc::slot<bool, IOCondition>& slot, PollFD::fd_t fd, IOCondition condition,
309     int priority = PRIORITY_DEFAULT);
310 
311   /** Connects an I/O handler that watches an I/O channel.
312    * @code
313    * bool io_handler(Glib::IOCondition io_condition) { ... }
314    * Glib::signal_io().connect(sigc::ptr_fun(&io_handler), channel, Glib::IO_IN | Glib::IO_HUP);
315    * @endcode
316    * is equivalent to:
317    * @code
318    * bool io_handler(Glib::IOCondition io_condition) { ... }
319    * const auto io_source = Glib::IOSource::create(channel, Glib::IO_IN | Glib::IO_HUP);
320    * io_source->connect(sigc::ptr_fun(&io_handler));
321    * io_source->attach(Glib::MainContext::get_default());
322    * @endcode
323    *
324    * This method is not thread-safe. You should call it, or manipulate the
325    * returned sigc::connection object, only from the thread where the SignalIO
326    * object's MainContext runs.
327    *
328    * @param slot A slot to call when polling @a channel results in an event that matches @a
329    * condition.
330    * The event will be passed as a parameter to @a slot.
331    * If <tt>io_handler()</tt> returns <tt>false</tt> the handler is disconnected.
332    * @param channel The IOChannel object to watch.
333    * @param condition The conditions to watch for.
334    * @param priority The priority of the new event source.
335    * @return A connection handle, which can be used to disconnect the handler.
336    */
337   sigc::connection connect(const sigc::slot<bool, IOCondition>& slot,
338     const Glib::RefPtr<IOChannel>& channel, IOCondition condition, int priority = PRIORITY_DEFAULT);
339 
340 private:
341   GMainContext* context_;
342 
343   // no copy assignment
344   SignalIO& operator=(const SignalIO&);
345 };
346 
347 class GLIBMM_API SignalChildWatch
348 {
349 public:
350 #ifndef DOXYGEN_SHOULD_SKIP_THIS
351   explicit inline SignalChildWatch(GMainContext* context);
352 #endif
353   /** Connects a child watch handler.
354    * @code
355    * void child_watch_handler(GPid pid, int child_status) { ... }
356    * Glib::signal_child_watch().connect(sigc::ptr_fun(&child_watch_handler), pid);
357    * @endcode
358    *
359    * This method is not thread-safe. You should call it, or manipulate the
360    * returned sigc::connection object, only from the thread where the SignalChildWatch
361    * object's MainContext runs.
362    *
363    * @param slot A slot to call when child process @a pid exited.
364    * @param pid The child process to watch for.
365    * @param priority The priority of the new event source.
366    * @return A connection handle, which can be used to disconnect the handler.
367    */
368   sigc::connection connect(
369     const sigc::slot<void, GPid, int>& slot, GPid pid, int priority = PRIORITY_DEFAULT);
370 
371 private:
372   GMainContext* context_;
373 
374   // no copy assignment
375   SignalChildWatch& operator=(const SignalChildWatch&);
376 };
377 
378 /** Convenience timeout signal.
379  * @return A signal proxy; you want to use SignalTimeout::connect().
380  */
381 GLIBMM_API
382 SignalTimeout signal_timeout();
383 
384 /** Convenience idle signal.
385  * @return A signal proxy; you want to use SignalIdle::connect().
386  */
387 GLIBMM_API
388 SignalIdle signal_idle();
389 
390 /** Convenience I/O signal.
391  * @return A signal proxy; you want to use SignalIO::connect().
392  */
393 GLIBMM_API
394 SignalIO signal_io();
395 
396 /** Convenience child watch signal.
397  * @return A signal proxy; you want to use SignalChildWatch::connect().
398  */
399 GLIBMM_API
400 SignalChildWatch signal_child_watch();
401 
402 /** Main context.
403  */
404 class GLIBMM_API MainContext
405 {
406 public:
407   using CppObjectType = Glib::MainContext;
408   using BaseObjectType = GMainContext;
409 
410   // noncopyable
411   MainContext(const MainContext& other) = delete;
412   MainContext& operator=(const MainContext& other) = delete;
413 
414   /** Creates a new MainContext.
415    * @return The new MainContext.
416    */
417   static Glib::RefPtr<MainContext> create();
418 
419   /** Returns the global default main context.
420    * This is the main context used for main loop functions when a main loop
421    * is not explicitly specified, and corresponds to the "main" main loop.
422    *
423    * @return The global default main context.
424    * @see get_thread_default()
425    */
426   static Glib::RefPtr<MainContext> get_default();
427 
428   /** Runs a single iteration for the given main loop.
429    * This involves checking to see if any event sources are ready to be processed, then if no events
430    * sources are
431    * ready and may_block is true, waiting for a source to become ready, then dispatching the highest
432    * priority events
433    * sources that are ready. Note that even when may_block is true, it is still possible for
434    * iteration() to return
435    * false, since the the wait may be interrupted for other reasons than an event source becoming
436    * ready.
437    * @param may_block Whether the call may block.
438    * @return true if events were dispatched.
439    */
440   bool iteration(bool may_block);
441 
442   /** Checks if any sources have pending events for the given context.
443    * @return true if events are pending.
444    */
445   bool pending();
446 
447   /** If context is currently waiting in a poll(), interrupt the poll(), and continue the iteration
448    * process.
449    */
450   void wakeup();
451 
452   /** Tries to become the owner of the specified context.
453    * If some other thread is the owner of the context, returns <tt>false</tt> immediately. Ownership
454    * is properly recursive:
455    * the owner can require ownership again and will release ownership when release() is called as
456    * many times as
457    * acquire().
458    * You must be the owner of a context before you can call prepare(), query(), check(), dispatch().
459    * @return true if the operation succeeded, and this thread is now the owner of context.
460    */
461   bool acquire();
462 
463 #ifndef GLIBMM_DISABLE_DEPRECATED
464   /** Tries to become the owner of the specified context, as with acquire().
465    * But if another thread is the owner, atomically drop mutex and wait on cond
466    * until that owner releases ownership or until cond is signaled, then try
467    * again (once) to become the owner.
468    * @param cond A condition variable.
469    * @param mutex A mutex, currently held.
470    * @return true if the operation succeeded, and this thread is now the owner of context.
471    *
472    * @deprecated Use the underlying g_main_context_is_owner() function
473    *   and separate locking, if you really need this functionality.
474    */
475   bool wait(Glib::Cond& cond, Glib::Mutex& mutex);
476 
477   /** Tries to become the owner of the specified context, as with acquire().
478    * But if another thread is the owner, atomically drop mutex and wait on cond
479    * until that owner releases ownership or until cond is signaled, then try
480    * again (once) to become the owner.
481    * @param cond A condition variable.
482    * @param mutex A mutex, currently held.
483    * @return true if the operation succeeded, and this thread is now the owner of context.
484    *
485    * @deprecated Use the underlying g_main_context_is_owner() function
486    *   and separate locking, if you really need this functionality.
487    */
488   bool wait(Glib::Threads::Cond& cond, Glib::Threads::Mutex& mutex);
489 #endif // GLIBMM_DISABLE_DEPRECATED
490 
491   /** Releases ownership of a context previously acquired by this thread with acquire(). If the
492    * context was acquired
493    * multiple times, the only release ownership when release() is called as many times as it was
494    * acquired.
495    */
496   void release();
497 
498   /** Prepares to poll sources within a main loop. The resulting information for polling is
499    * determined by calling query().
500    * @param priority Location to store priority of highest priority source already ready.
501    * @return true if some source is ready to be dispatched prior to polling.
502    */
503   bool prepare(int& priority);
504   /** Prepares to poll sources within a main loop. The resulting information for polling is
505    * determined by calling query().
506    * @return true if some source is ready to be dispatched prior to polling.
507    */
508   bool prepare();
509 
510   /** Determines information necessary to poll this main loop.
511    * @param max_priority Maximum priority source to check.
512    * @param timeout Location to store timeout to be used in polling.
513    * @param fds Location to store Glib::PollFD records that need to be polled.
514    * @return the number of records actually stored in fds, or, if more than n_fds records need to be
515    * stored, the number of records that need to be stored.
516    */
517   void query(int max_priority, int& timeout, std::vector<PollFD>& fds);
518 
519   /** Passes the results of polling back to the main loop.
520    * @param max_priority Maximum numerical priority of sources to check.
521    * @param fds Vector of Glib::PollFD's that was passed to the last call to query()
522    * @return true if some sources are ready to be dispatched.
523    */
524   bool check(int max_priority, std::vector<PollFD>& fds);
525 
526   /** Dispatches all pending sources.
527    */
528   void dispatch();
529 
530   // TODO: Use slot instead?
531   /** Sets the function to use to handle polling of file descriptors. It will be used instead of the
532    * poll() system call (or GLib's replacement function, which is used where poll() isn't
533    * available).
534    * This function could possibly be used to integrate the GLib event loop with an external event
535    * loop.
536    * @param poll_func The function to call to poll all file descriptors.
537    */
538   void set_poll_func(GPollFunc poll_func);
539 
540   /** Gets the poll function set by g_main_context_set_poll_func().
541    * @return The poll function
542    */
543   GPollFunc get_poll_func();
544 
545   /** Adds a file descriptor to the set of file descriptors polled for this context. This will very
546    * seldomly be used directly. Instead a typical event source will use Glib::Source::add_poll()
547    * instead.
548    * @param fd A PollFD structure holding information about a file descriptor to watch.
549    * @param priority The priority for this file descriptor which should be the same as the priority
550    * used for Glib::Source::attach() to ensure that the file descriptor is polled whenever the
551    * results may be needed.
552    */
553   void add_poll(PollFD& fd, int priority);
554 
555   /** Removes file descriptor from the set of file descriptors to be polled for a particular
556    * context.
557    * @param fd A PollFD structure holding information about a file descriptor.
558    */
559   void remove_poll(PollFD& fd);
560 
561   /** Acquires the context and sets it as the thread-default context for the current thread.
562    *
563    * This will cause certain asynchronous operations (such as most gio-based I/O)
564    * which are started in this thread to run under this context and deliver their
565    * results to its main loop, rather than running under the global
566    * default context in the main thread. Note that calling this function
567    * changes the context returned by get_thread_default(),
568    * not the one returned by get_default(), so it does not affect
569    * the context used by functions like g_idle_add().
570    *
571    * Normally you would call this function shortly after creating a new
572    * thread, passing it a Glib::MainContext which will be run by a
573    * Glib::MainLoop in that thread, to set a new default context for all
574    * async operations in that thread. In this case you may not need to
575    * ever call pop_thread_default(), assuming you want the
576    * new Glib::MainContext to be the default for the whole lifecycle of the
577    * thread.
578    *
579    * If you don't have control over how the new thread was created (e.g.
580    * if the new thread isn't newly created, or if the thread life
581    * cycle is managed by a GThreadPool), it is always suggested to wrap
582    * the logic that needs to use the new Glib::MainContext inside a
583    * push_thread_default() / pop_thread_default()
584    * pair, otherwise threads that are re-used will end up never explicitly
585    * releasing the Glib::MainContext reference they hold.
586    *
587    * In some cases you may want to schedule a single operation in a
588    * non-default context, or temporarily use a non-default context in
589    * the main thread. In that case, you can wrap the call to the
590    * asynchronous operation inside a push_thread_default() / pop_thread_default()
591    * pair, but it is up to you to ensure that no other asynchronous operations
592    * accidentally get started while the non-default context is active.
593    *
594    * Beware that libraries that predate this function may not correctly
595    * handle being used from a thread with a thread-default context. Eg,
596    * see Gio::File::supports_thread_contexts().
597    *
598    * @newin{2,64}
599    */
600   void push_thread_default();
601 
602   /** Pops the context off the thread-default context stack (verifying that
603    * it was on the top of the stack).
604    *
605    * @newin{2,64}
606    */
607   void pop_thread_default();
608 
609   /** Gets the thread-default MainContext for this thread.
610    * Asynchronous operations that want to be able to be run in contexts
611    * other than the default one should call this method to get a MainContext
612    * to add their Glib::Sources to. (Note that even in single-threaded
613    * programs applications may sometimes want to temporarily push a
614    * non-default context, so it is not safe to assume that this will
615    * always return the global default context if you are running in
616    * the default thread.)
617    *
618    * This method wraps g_main_context_ref_thread_default(),
619    * and not g_main_context_get_thread_default().
620    *
621    * @return The thread-default MainContext.
622    *
623    * @newin{2,64}
624    */
625   static Glib::RefPtr<MainContext> get_thread_default();
626 
627   /** Invokes a function in such a way that this MainContext is owned during
628    * the invocation of @a slot.
629    *
630    * If the context is owned by the current thread, @a slot is called
631    * directly. Otherwise, if the context is the thread-default main context
632    * of the current thread and acquire() succeeds, then
633    * @a slot is called and release() is called afterwards.
634    *
635    * In any other case, an idle source is created to call @a slot and
636    * that source is attached to the context (presumably to be run in another
637    * thread).
638    *
639    * Note that, as with normal idle functions, @a slot should probably
640    * return <tt>false</tt>. If it returns <tt>true</tt>, it will be continuously
641    * run in a loop (and may prevent this call from returning).
642    *
643    * If an idle source is created to call @a slot, invoke() may return before
644    * @a slot is called.
645    *
646    * Because sigc::trackable is not thread-safe, if the slot represents a
647    * non-static method of a class deriving from sigc::trackable, and the slot is
648    * created by sigc::mem_fun(), invoke() should only be called from
649    * the thread where the context runs. You can use, say, boost::bind() or,
650    * in C++11, std::bind() or a C++11 lambda expression instead of sigc::mem_fun().
651    *
652    * @param slot A slot to call.
653    * @param priority The priority of the idle source, if one is created.
654    *
655    * @newin{2,38}
656    */
657   void invoke(const sigc::slot<bool>& slot, int priority = PRIORITY_DEFAULT);
658 
659   /** Timeout signal, attached to this MainContext.
660    * @return A signal proxy; you want to use SignalTimeout::connect().
661    */
662   SignalTimeout signal_timeout();
663 
664   /** Idle signal, attached to this MainContext.
665    * @return A signal proxy; you want to use SignalIdle::connect().
666    */
667   SignalIdle signal_idle();
668 
669   /** I/O signal, attached to this MainContext.
670    * @return A signal proxy; you want to use SignalIO::connect().
671    */
672   SignalIO signal_io();
673 
674   /** child watch signal, attached to this MainContext.
675    * @return A signal proxy; you want to use SignalChildWatch::connect().
676    */
677   SignalChildWatch signal_child_watch();
678 
679   void reference() const;
680   void unreference() const;
681 
682   GMainContext* gobj();
683   const GMainContext* gobj() const;
684   GMainContext* gobj_copy() const;
685 
686 private:
687   // Glib::MainContext can neither be constructed nor deleted.
688   MainContext();
689   void operator delete(void*, std::size_t);
690 };
691 
692 /** @relates Glib::MainContext */
693 GLIBMM_API
694 Glib::RefPtr<MainContext> wrap(GMainContext* gobject, bool take_copy = false);
695 
696 class GLIBMM_API MainLoop
697 {
698 public:
699   using CppObjectType = Glib::MainLoop;
700   using BaseObjectType = GMainLoop;
701 
702   static Glib::RefPtr<MainLoop> create(bool is_running = false);
703   static Glib::RefPtr<MainLoop> create(
704     const Glib::RefPtr<MainContext>& context, bool is_running = false);
705 
706   /** Runs a main loop until quit() is called on the loop.
707    * If this is called for the thread of the loop's MainContext, it will process events from the
708    * loop, otherwise it will simply wait.
709    */
710   void run();
711 
712   /** Stops a MainLoop from running. Any calls to run() for the loop will return.
713    */
714   void quit();
715 
716   /** Checks to see if the main loop is currently being run via run().
717    * @return true if the mainloop is currently being run.
718    */
719   bool is_running();
720 
721   /** Returns the MainContext of loop.
722    * @return The MainContext of loop.
723    */
724   Glib::RefPtr<MainContext> get_context();
725 
726   // TODO: C++ize the (big) g_main_depth docs here.
727   static int depth();
728 
729   /** Increases the reference count on a MainLoop object by one.
730    */
731   void reference() const;
732 
733   /** Decreases the reference count on a MainLoop object by one.
734    * If the result is zero, free the loop and free all associated memory.
735    */
736   void unreference() const;
737 
738   GMainLoop* gobj();
739   const GMainLoop* gobj() const;
740   GMainLoop* gobj_copy() const;
741 
742 private:
743   // Glib::MainLoop can neither be constructed nor deleted.
744   MainLoop();
745   void operator delete(void*, std::size_t);
746 
747   MainLoop(const MainLoop&);
748   MainLoop& operator=(const MainLoop&);
749 };
750 
751 /** @relates Glib::MainLoop */
752 GLIBMM_API
753 Glib::RefPtr<MainLoop> wrap(GMainLoop* gobject, bool take_copy = false);
754 
755 class GLIBMM_API Source
756 {
757 public:
758   using CppObjectType = Glib::Source;
759   using BaseObjectType = GSource;
760 
761   // noncopyable
762   Source(const Source&) = delete;
763   Source& operator=(const Source&) = delete;
764 
765   static Glib::RefPtr<Source> create() /* = 0 */;
766 
767   /** Adds a Source to a context so that it will be executed within that context.
768    * @param context A MainContext.
769    * @return The ID for the source within the MainContext.
770    */
771   unsigned int attach(const Glib::RefPtr<MainContext>& context);
772 
773   /** Adds a Source to a context so that it will be executed within that context.
774    * The default context will be used.
775    * @return The ID for the source within the MainContext.
776    */
777   unsigned int attach();
778 
779   // TODO: Does this destroy step make sense in C++? Should it just be something that happens in a
780   // destructor?
781 
782   /** Removes a source from its MainContext, if any, and marks it as destroyed.
783    * The source cannot be subsequently added to another context.
784    */
785   void destroy();
786 
787   /** Sets the priority of a source. While the main loop is being run, a source will be dispatched
788    * if it is ready to be dispatched and no sources at a higher (numerically smaller) priority are
789    * ready to be dispatched.
790    * @param priority The new priority.
791    */
792   void set_priority(int priority);
793 
794   /** Gets the priority of a source.
795    * @return The priority of the source.
796    */
797   int get_priority() const;
798 
799   /** Sets whether a source can be called recursively.
800    * If @a can_recurse is true, then while the source is being dispatched then this source will be
801    * processed normally. Otherwise, all processing of this source is blocked until the dispatch
802    * function returns.
803    * @param can_recurse Whether recursion is allowed for this source.
804    */
805   void set_can_recurse(bool can_recurse);
806 
807   /** Checks whether a source is allowed to be called recursively. see set_can_recurse().
808    * @return Whether recursion is allowed.
809    */
810   bool get_can_recurse() const;
811 
812   /** Returns the numeric ID for a particular source.
813    * The ID of a source is unique within a particular main loop context. The reverse mapping from ID
814    * to source is done by MainContext::find_source_by_id().
815    * @return The ID for the source.
816    */
817   unsigned int get_id() const;
818 
819   // TODO: Add a const version of this method?
820   /** Gets the MainContext with which the source is associated.
821    * Calling this function on a destroyed source is an error.
822    * @return The MainContext with which the source is associated, or a null RefPtr if the context
823    * has not yet been added to a source.
824    */
825   Glib::RefPtr<MainContext> get_context();
826 
gobj()827   GSource* gobj() { return gobject_; }
gobj()828   const GSource* gobj() const { return gobject_; }
829   GSource* gobj_copy() const;
830 
831   void reference() const;
832   void unreference() const;
833 
834 protected:
835   /** Construct an object that uses the virtual functions prepare(), check() and dispatch().
836    */
837   Source();
838 
839   /** Wrap an existing GSource object and install the given callback function.
840    * The constructed object doesn't use the virtual functions prepare(), check() and dispatch().
841    * This constructor is for use by derived types that need to wrap a GSource object.
842    * The callback function can be a static member function. But beware -
843    * depending on the actual implementation of the GSource's virtual functions
844    * the expected type of the callback function can differ from GSourceFunc.
845    */
846   Source(GSource* cast_item, GSourceFunc callback_func);
847 
848   virtual ~Source() noexcept;
849 
850   sigc::connection connect_generic(const sigc::slot_base& slot);
851 
852   /** Adds a file descriptor to the set of file descriptors polled for this source.
853    * The event source's check function will typically test the revents field in the PollFD  and
854    * return true if events need to be processed.
855    * @param poll_fd A PollFD object holding information about a file descriptor to watch.
856    */
857   void add_poll(PollFD& poll_fd);
858 
859   /** Removes a file descriptor from the set of file descriptors polled for this source.
860    * @param poll_fd A PollFD object previously passed to add_poll().
861    */
862   void remove_poll(PollFD& poll_fd);
863 
864 #ifndef GLIBMM_DISABLE_DEPRECATED
865   /** Gets the "current time" to be used when checking this source.
866    *
867    * @param[out] current_time Glib::TimeVal in which to store current time.
868    *
869    * @deprecated Use get_time() instead.
870    */
871   void get_current_time(Glib::TimeVal& current_time);
872 #endif // GLIBMM_DISABLE_DEPRECATED
873 
874   // TODO: Remove mention of g_get_monotonic time when we wrap it in C++.
875   /** Gets the time to be used when checking this source. The advantage of
876    * calling this function over calling g_get_monotonic_time() directly is
877    * that when checking multiple sources, GLib can cache a single value
878    * instead of having to repeatedly get the system monotonic time.
879    *
880    * The time here is the system monotonic time, if available, or some
881    * other reasonable alternative otherwise.  See g_get_monotonic_time().
882    *
883    * @result The monotonic time in microseconds.
884    *
885    * @newin{2,28}
886    */
887   gint64 get_time() const;
888 
889   virtual bool prepare(int& timeout) = 0;
890   virtual bool check() = 0;
891   virtual bool dispatch(sigc::slot_base* slot) = 0;
892 
893 private:
894   GSource* gobject_;
895 
896 #ifndef DOXYGEN_SHOULD_SKIP_THIS
897   static inline Source* get_wrapper(GSource* source);
898 
899   static const GSourceFuncs vfunc_table_;
900 
901   static gboolean prepare_vfunc(GSource* source, int* timeout);
902   static gboolean check_vfunc(GSource* source);
903   static gboolean dispatch_vfunc(GSource* source, GSourceFunc callback, void* user_data);
904 
905 public:
906   static void destroy_notify_callback(void* data);
907   // Used by SignalXyz, possibly in other files.
908   static sigc::connection attach_signal_source(const sigc::slot_base& slot, int priority,
909     GSource* source, GMainContext* context, GSourceFunc callback_func);
910   // Used by SignalXyz in other files.
911   static sigc::slot_base* get_slot_from_connection_node(void* data);
912   // Used by derived Source classes in other files.
913   static sigc::slot_base* get_slot_from_callback_data(void* data);
914 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
915 };
916 
917 class GLIBMM_API TimeoutSource : public Glib::Source
918 {
919 public:
920   using CppObjectType = Glib::TimeoutSource;
921 
922   static Glib::RefPtr<TimeoutSource> create(unsigned int interval);
923   sigc::connection connect(const sigc::slot<bool>& slot);
924 
925 protected:
926   explicit TimeoutSource(unsigned int interval);
927   ~TimeoutSource() noexcept override;
928 
929   bool prepare(int& timeout) override;
930   bool check() override;
931   bool dispatch(sigc::slot_base* slot) override;
932 
933 private:
934   // TODO: Replace with gint64, because TimeVal is deprecated, when we can break ABI.
935   Glib::TimeVal expiration_;
936 
937   unsigned int interval_;
938 };
939 
940 class GLIBMM_API IdleSource : public Glib::Source
941 {
942 public:
943   using CppObjectType = Glib::IdleSource;
944 
945   static Glib::RefPtr<IdleSource> create();
946   sigc::connection connect(const sigc::slot<bool>& slot);
947 
948 protected:
949   IdleSource();
950   ~IdleSource() noexcept override;
951 
952   bool prepare(int& timeout) override;
953   bool check() override;
954   bool dispatch(sigc::slot_base* slot_data) override;
955 };
956 
957 class GLIBMM_API IOSource : public Glib::Source
958 {
959 public:
960   using CppObjectType = Glib::IOSource;
961 
962   static Glib::RefPtr<IOSource> create(PollFD::fd_t fd, IOCondition condition);
963   static Glib::RefPtr<IOSource> create(
964     const Glib::RefPtr<IOChannel>& channel, IOCondition condition);
965   sigc::connection connect(const sigc::slot<bool, IOCondition>& slot);
966 
967 protected:
968   IOSource(PollFD::fd_t fd, IOCondition condition);
969   IOSource(const Glib::RefPtr<IOChannel>& channel, IOCondition condition);
970 
971   /** Wrap an existing GSource object and install the given callback function.
972    * This constructor is for use by derived types that need to wrap a GSource object.
973    * @see Source::Source(GSource*, GSourceFunc).
974    * @newin{2,42}
975    */
976   IOSource(GSource* cast_item, GSourceFunc callback_func);
977 
978   ~IOSource() noexcept override;
979 
980   bool prepare(int& timeout) override;
981   bool check() override;
982   bool dispatch(sigc::slot_base* slot) override;
983 
984 private:
985   PollFD poll_fd_;
986 };
987 
988 /** @} group MainLoop */
989 
990 } // namespace Glib
991 
992 #endif /* _GLIBMM_MAIN_H */
993