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