dbus-mainloop.c revision a683a80c409cc4f2e57ba6a3e60d52f91b8657d0
1/* -*- mode: C; c-file-style: "gnu" -*- */ 2/* dbus-mainloop.c Main loop utility 3 * 4 * Copyright (C) 2003 Red Hat, Inc. 5 * 6 * Licensed under the Academic Free License version 1.2 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 */ 23 24#include "dbus-mainloop.h" 25 26#ifndef DOXYGEN_SHOULD_SKIP_THIS 27 28#include <dbus/dbus-list.h> 29#include <dbus/dbus-sysdeps.h> 30 31#define MAINLOOP_SPEW 0 32 33struct DBusLoop 34{ 35 int refcount; 36 DBusList *callbacks; 37 int callback_list_serial; 38 int watch_count; 39 int timeout_count; 40 int depth; /**< number of recursive runs */ 41 DBusList *need_dispatch; 42}; 43 44typedef enum 45{ 46 CALLBACK_WATCH, 47 CALLBACK_TIMEOUT 48} CallbackType; 49 50typedef struct 51{ 52 int refcount; 53 CallbackType type; 54 void *data; 55 DBusFreeFunction free_data_func; 56} Callback; 57 58typedef struct 59{ 60 Callback callback; 61 DBusWatchFunction function; 62 DBusWatch *watch; 63 /* last watch handle failed due to OOM */ 64 unsigned int last_iteration_oom : 1; 65} WatchCallback; 66 67typedef struct 68{ 69 Callback callback; 70 DBusTimeout *timeout; 71 DBusTimeoutFunction function; 72 unsigned long last_tv_sec; 73 unsigned long last_tv_usec; 74} TimeoutCallback; 75 76#define WATCH_CALLBACK(callback) ((WatchCallback*)callback) 77#define TIMEOUT_CALLBACK(callback) ((TimeoutCallback*)callback) 78 79static WatchCallback* 80watch_callback_new (DBusWatch *watch, 81 DBusWatchFunction function, 82 void *data, 83 DBusFreeFunction free_data_func) 84{ 85 WatchCallback *cb; 86 87 cb = dbus_new (WatchCallback, 1); 88 if (cb == NULL) 89 return NULL; 90 91 cb->watch = watch; 92 cb->function = function; 93 cb->last_iteration_oom = FALSE; 94 cb->callback.refcount = 1; 95 cb->callback.type = CALLBACK_WATCH; 96 cb->callback.data = data; 97 cb->callback.free_data_func = free_data_func; 98 99 return cb; 100} 101 102static TimeoutCallback* 103timeout_callback_new (DBusTimeout *timeout, 104 DBusTimeoutFunction function, 105 void *data, 106 DBusFreeFunction free_data_func) 107{ 108 TimeoutCallback *cb; 109 110 cb = dbus_new (TimeoutCallback, 1); 111 if (cb == NULL) 112 return NULL; 113 114 cb->timeout = timeout; 115 cb->function = function; 116 _dbus_get_current_time (&cb->last_tv_sec, 117 &cb->last_tv_usec); 118 cb->callback.refcount = 1; 119 cb->callback.type = CALLBACK_TIMEOUT; 120 cb->callback.data = data; 121 cb->callback.free_data_func = free_data_func; 122 123 return cb; 124} 125 126static void 127callback_ref (Callback *cb) 128{ 129 _dbus_assert (cb->refcount > 0); 130 131 cb->refcount += 1; 132} 133 134static void 135callback_unref (Callback *cb) 136{ 137 _dbus_assert (cb->refcount > 0); 138 139 cb->refcount -= 1; 140 141 if (cb->refcount == 0) 142 { 143 if (cb->free_data_func) 144 (* cb->free_data_func) (cb->data); 145 146 dbus_free (cb); 147 } 148} 149 150static dbus_bool_t 151add_callback (DBusLoop *loop, 152 Callback *cb) 153{ 154 if (!_dbus_list_append (&loop->callbacks, cb)) 155 return FALSE; 156 157 loop->callback_list_serial += 1; 158 159 switch (cb->type) 160 { 161 case CALLBACK_WATCH: 162 loop->watch_count += 1; 163 break; 164 case CALLBACK_TIMEOUT: 165 loop->timeout_count += 1; 166 break; 167 } 168 169 return TRUE; 170} 171 172static void 173remove_callback (DBusLoop *loop, 174 DBusList *link) 175{ 176 Callback *cb = link->data; 177 178 switch (cb->type) 179 { 180 case CALLBACK_WATCH: 181 loop->watch_count -= 1; 182 break; 183 case CALLBACK_TIMEOUT: 184 loop->timeout_count -= 1; 185 break; 186 } 187 188 callback_unref (cb); 189 _dbus_list_remove_link (&loop->callbacks, link); 190 loop->callback_list_serial += 1; 191} 192 193DBusLoop* 194_dbus_loop_new (void) 195{ 196 DBusLoop *loop; 197 198 loop = dbus_new0 (DBusLoop, 1); 199 if (loop == NULL) 200 return NULL; 201 202 loop->refcount = 1; 203 204 return loop; 205} 206 207void 208_dbus_loop_ref (DBusLoop *loop) 209{ 210 _dbus_assert (loop != NULL); 211 _dbus_assert (loop->refcount > 0); 212 213 loop->refcount += 1; 214} 215 216void 217_dbus_loop_unref (DBusLoop *loop) 218{ 219 _dbus_assert (loop != NULL); 220 _dbus_assert (loop->refcount > 0); 221 222 loop->refcount -= 1; 223 if (loop->refcount == 0) 224 { 225 while (loop->need_dispatch) 226 { 227 DBusConnection *connection = _dbus_list_pop_first (&loop->need_dispatch); 228 229 dbus_connection_unref (connection); 230 } 231 232 dbus_free (loop); 233 } 234} 235 236dbus_bool_t 237_dbus_loop_add_watch (DBusLoop *loop, 238 DBusWatch *watch, 239 DBusWatchFunction function, 240 void *data, 241 DBusFreeFunction free_data_func) 242{ 243 WatchCallback *wcb; 244 245 wcb = watch_callback_new (watch, function, data, free_data_func); 246 if (wcb == NULL) 247 return FALSE; 248 249 if (!add_callback (loop, (Callback*) wcb)) 250 { 251 wcb->callback.free_data_func = NULL; /* don't want to have this side effect */ 252 callback_unref ((Callback*) wcb); 253 return FALSE; 254 } 255 256 return TRUE; 257} 258 259void 260_dbus_loop_remove_watch (DBusLoop *loop, 261 DBusWatch *watch, 262 DBusWatchFunction function, 263 void *data) 264{ 265 DBusList *link; 266 267 link = _dbus_list_get_first_link (&loop->callbacks); 268 while (link != NULL) 269 { 270 DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); 271 Callback *this = link->data; 272 273 if (this->type == CALLBACK_WATCH && 274 WATCH_CALLBACK (this)->watch == watch && 275 this->data == data && 276 WATCH_CALLBACK (this)->function == function) 277 { 278 remove_callback (loop, link); 279 280 return; 281 } 282 283 link = next; 284 } 285 286 _dbus_warn ("could not find watch %p function %p data %p to remove\n", 287 watch, (void *)function, data); 288} 289 290dbus_bool_t 291_dbus_loop_add_timeout (DBusLoop *loop, 292 DBusTimeout *timeout, 293 DBusTimeoutFunction function, 294 void *data, 295 DBusFreeFunction free_data_func) 296{ 297 TimeoutCallback *tcb; 298 299 tcb = timeout_callback_new (timeout, function, data, free_data_func); 300 if (tcb == NULL) 301 return FALSE; 302 303 if (!add_callback (loop, (Callback*) tcb)) 304 { 305 tcb->callback.free_data_func = NULL; /* don't want to have this side effect */ 306 callback_unref ((Callback*) tcb); 307 return FALSE; 308 } 309 310 return TRUE; 311} 312 313void 314_dbus_loop_remove_timeout (DBusLoop *loop, 315 DBusTimeout *timeout, 316 DBusTimeoutFunction function, 317 void *data) 318{ 319 DBusList *link; 320 321 link = _dbus_list_get_first_link (&loop->callbacks); 322 while (link != NULL) 323 { 324 DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); 325 Callback *this = link->data; 326 327 if (this->type == CALLBACK_TIMEOUT && 328 TIMEOUT_CALLBACK (this)->timeout == timeout && 329 this->data == data && 330 TIMEOUT_CALLBACK (this)->function == function) 331 { 332 remove_callback (loop, link); 333 334 return; 335 } 336 337 link = next; 338 } 339 340 _dbus_warn ("could not find timeout %p function %p data %p to remove\n", 341 timeout, (void *)function, data); 342} 343 344/* Convolutions from GLib, there really must be a better way 345 * to do this. 346 */ 347static dbus_bool_t 348check_timeout (unsigned long tv_sec, 349 unsigned long tv_usec, 350 TimeoutCallback *tcb, 351 int *timeout) 352{ 353 long sec_remaining; 354 long msec_remaining; 355 unsigned long expiration_tv_sec; 356 unsigned long expiration_tv_usec; 357 long interval_seconds; 358 long interval_milliseconds; 359 int interval; 360 361 /* I'm pretty sure this function could suck (a lot) less */ 362 363 interval = dbus_timeout_get_interval (tcb->timeout); 364 365 interval_seconds = interval / 1000L; 366 interval_milliseconds = interval % 1000L; 367 368 expiration_tv_sec = tcb->last_tv_sec + interval_seconds; 369 expiration_tv_usec = tcb->last_tv_usec + interval_milliseconds * 1000; 370 if (expiration_tv_usec >= 1000000) 371 { 372 expiration_tv_usec -= 1000000; 373 expiration_tv_sec += 1; 374 } 375 376 sec_remaining = expiration_tv_sec - tv_sec; 377 /* need to force this to be signed, as it is intended to sometimes 378 * produce a negative result 379 */ 380 msec_remaining = ((long) expiration_tv_usec - (long) tv_usec) / 1000L; 381 382#if MAINLOOP_SPEW 383 _dbus_verbose ("Interval is %ld seconds %ld msecs\n", 384 interval_seconds, 385 interval_milliseconds); 386 _dbus_verbose ("Now is %lu seconds %lu usecs\n", 387 tv_sec, tv_usec); 388 _dbus_verbose ("Last is %lu seconds %lu usecs\n", 389 tcb->last_tv_sec, tcb->last_tv_usec); 390 _dbus_verbose ("Exp is %lu seconds %lu usecs\n", 391 expiration_tv_sec, expiration_tv_usec); 392 _dbus_verbose ("Pre-correction, sec_remaining %ld msec_remaining %ld\n", 393 sec_remaining, msec_remaining); 394#endif 395 396 /* We do the following in a rather convoluted fashion to deal with 397 * the fact that we don't have an integral type big enough to hold 398 * the difference of two timevals in milliseconds. 399 */ 400 if (sec_remaining < 0 || (sec_remaining == 0 && msec_remaining < 0)) 401 { 402 *timeout = 0; 403 } 404 else 405 { 406 if (msec_remaining < 0) 407 { 408 msec_remaining += 1000; 409 sec_remaining -= 1; 410 } 411 412 if (sec_remaining > (_DBUS_INT_MAX / 1000) || 413 msec_remaining > _DBUS_INT_MAX) 414 *timeout = _DBUS_INT_MAX; 415 else 416 *timeout = sec_remaining * 1000 + msec_remaining; 417 } 418 419 if (*timeout > interval) 420 { 421 /* This indicates that the system clock probably moved backward */ 422 _dbus_verbose ("System clock set backward! Resetting timeout.\n"); 423 424 tcb->last_tv_sec = tv_sec; 425 tcb->last_tv_usec = tv_usec; 426 427 *timeout = interval; 428 } 429 430#if MAINLOOP_SPEW 431 _dbus_verbose (" timeout expires in %d milliseconds\n", *timeout); 432#endif 433 434 return *timeout == 0; 435} 436 437dbus_bool_t 438_dbus_loop_dispatch (DBusLoop *loop) 439{ 440 441#if MAINLOOP_SPEW 442 _dbus_verbose (" %d connections to dispatch\n", _dbus_list_get_length (&loop->need_dispatch)); 443#endif 444 445 if (loop->need_dispatch == NULL) 446 return FALSE; 447 448 next: 449 while (loop->need_dispatch != NULL) 450 { 451 DBusConnection *connection = _dbus_list_pop_first (&loop->need_dispatch); 452 453 while (TRUE) 454 { 455 DBusDispatchStatus status; 456 457 status = dbus_connection_dispatch (connection); 458 459 if (status == DBUS_DISPATCH_COMPLETE) 460 { 461 dbus_connection_unref (connection); 462 goto next; 463 } 464 else 465 { 466 if (status == DBUS_DISPATCH_NEED_MEMORY) 467 _dbus_wait_for_memory (); 468 } 469 } 470 } 471 472 return TRUE; 473} 474 475dbus_bool_t 476_dbus_loop_queue_dispatch (DBusLoop *loop, 477 DBusConnection *connection) 478{ 479 if (_dbus_list_append (&loop->need_dispatch, connection)) 480 { 481 dbus_connection_ref (connection); 482 return TRUE; 483 } 484 else 485 return FALSE; 486} 487 488/* Returns TRUE if we invoked any timeouts or have ready file 489 * descriptors, which is just used in test code as a debug hack 490 */ 491 492dbus_bool_t 493_dbus_loop_iterate (DBusLoop *loop, 494 dbus_bool_t block) 495{ 496#define N_STACK_DESCRIPTORS 64 497 dbus_bool_t retval; 498 DBusPollFD *fds; 499 DBusPollFD stack_fds[N_STACK_DESCRIPTORS]; 500 int n_fds; 501 WatchCallback **watches_for_fds; 502 WatchCallback *stack_watches_for_fds[N_STACK_DESCRIPTORS]; 503 int i; 504 DBusList *link; 505 int n_ready; 506 int initial_serial; 507 long timeout; 508 dbus_bool_t oom_watch_pending; 509 int orig_depth; 510 511 retval = FALSE; 512 513 fds = NULL; 514 watches_for_fds = NULL; 515 n_fds = 0; 516 oom_watch_pending = FALSE; 517 orig_depth = loop->depth; 518 519#if MAINLOOP_SPEW 520 _dbus_verbose ("Iteration block=%d depth=%d timeout_count=%d watch_count=%d\n", 521 block, loop->depth, loop->timeout_count, loop->watch_count); 522#endif 523 524 if (loop->callbacks == NULL) 525 goto next_iteration; 526 527 if (loop->watch_count > N_STACK_DESCRIPTORS) 528 { 529 fds = dbus_new0 (DBusPollFD, loop->watch_count); 530 531 while (fds == NULL) 532 { 533 _dbus_wait_for_memory (); 534 fds = dbus_new0 (DBusPollFD, loop->watch_count); 535 } 536 537 watches_for_fds = dbus_new (WatchCallback*, loop->watch_count); 538 while (watches_for_fds == NULL) 539 { 540 _dbus_wait_for_memory (); 541 watches_for_fds = dbus_new (WatchCallback*, loop->watch_count); 542 } 543 } 544 else 545 { 546 fds = stack_fds; 547 watches_for_fds = stack_watches_for_fds; 548 } 549 550 /* fill our array of fds and watches */ 551 n_fds = 0; 552 link = _dbus_list_get_first_link (&loop->callbacks); 553 while (link != NULL) 554 { 555 DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); 556 Callback *cb = link->data; 557 if (cb->type == CALLBACK_WATCH) 558 { 559 unsigned int flags; 560 WatchCallback *wcb = WATCH_CALLBACK (cb); 561 562 if (wcb->last_iteration_oom) 563 { 564 /* we skip this one this time, but reenable it next time, 565 * and have a timeout on this iteration 566 */ 567 wcb->last_iteration_oom = FALSE; 568 oom_watch_pending = TRUE; 569 570 retval = TRUE; /* return TRUE here to keep the loop going, 571 * since we don't know the watch is inactive 572 */ 573 574#if MAINLOOP_SPEW 575 _dbus_verbose (" skipping watch on fd %d as it was out of memory last time\n", 576 dbus_watch_get_fd (wcb->watch)); 577#endif 578 } 579 else if (dbus_watch_get_enabled (wcb->watch)) 580 { 581 watches_for_fds[n_fds] = wcb; 582 583 callback_ref (cb); 584 585 flags = dbus_watch_get_flags (wcb->watch); 586 587 fds[n_fds].fd = dbus_watch_get_fd (wcb->watch); 588 fds[n_fds].revents = 0; 589 fds[n_fds].events = 0; 590 if (flags & DBUS_WATCH_READABLE) 591 fds[n_fds].events |= _DBUS_POLLIN; 592 if (flags & DBUS_WATCH_WRITABLE) 593 fds[n_fds].events |= _DBUS_POLLOUT; 594 595#if MAINLOOP_SPEW 596 _dbus_verbose (" polling watch on fd %d\n", fds[n_fds].fd); 597#endif 598 599 n_fds += 1; 600 } 601 else 602 { 603#if MAINLOOP_SPEW 604 _dbus_verbose (" skipping disabled watch on fd %d\n", 605 dbus_watch_get_fd (wcb->watch)); 606#endif 607 } 608 } 609 610 link = next; 611 } 612 613 timeout = -1; 614 if (loop->timeout_count > 0) 615 { 616 unsigned long tv_sec; 617 unsigned long tv_usec; 618 619 _dbus_get_current_time (&tv_sec, &tv_usec); 620 621 link = _dbus_list_get_first_link (&loop->callbacks); 622 while (link != NULL) 623 { 624 DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); 625 Callback *cb = link->data; 626 627 if (cb->type == CALLBACK_TIMEOUT && 628 dbus_timeout_get_enabled (TIMEOUT_CALLBACK (cb)->timeout)) 629 { 630 TimeoutCallback *tcb = TIMEOUT_CALLBACK (cb); 631 int msecs_remaining; 632 633 check_timeout (tv_sec, tv_usec, tcb, &msecs_remaining); 634 635 if (timeout < 0) 636 timeout = msecs_remaining; 637 else 638 timeout = MIN (msecs_remaining, timeout); 639 640#if MAINLOOP_SPEW 641 _dbus_verbose (" timeout added, %d remaining, aggregate timeout %ld\n", 642 msecs_remaining, timeout); 643#endif 644 645 _dbus_assert (timeout >= 0); 646 647 if (timeout == 0) 648 break; /* it's not going to get shorter... */ 649 } 650#if MAINLOOP_SPEW 651 else if (cb->type == CALLBACK_TIMEOUT) 652 { 653 _dbus_verbose (" skipping disabled timeout\n"); 654 } 655#endif 656 657 link = next; 658 } 659 } 660 661 /* Never block if we have stuff to dispatch */ 662 if (!block || loop->need_dispatch != NULL) 663 { 664 timeout = 0; 665#if MAINLOOP_SPEW 666 _dbus_verbose (" timeout is 0 as we aren't blocking\n"); 667#endif 668 } 669 670 /* if a watch is OOM, don't wait longer than the OOM 671 * wait to re-enable it 672 */ 673 if (oom_watch_pending) 674 timeout = MIN (timeout, _dbus_get_oom_wait ()); 675 676#if MAINLOOP_SPEW 677 _dbus_verbose (" polling on %d descriptors timeout %ld\n", n_fds, timeout); 678#endif 679 680 n_ready = _dbus_poll (fds, n_fds, timeout); 681 682 initial_serial = loop->callback_list_serial; 683 684 if (loop->timeout_count > 0) 685 { 686 unsigned long tv_sec; 687 unsigned long tv_usec; 688 689 _dbus_get_current_time (&tv_sec, &tv_usec); 690 691 /* It'd be nice to avoid this O(n) thingy here */ 692 link = _dbus_list_get_first_link (&loop->callbacks); 693 while (link != NULL) 694 { 695 DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); 696 Callback *cb = link->data; 697 698 if (initial_serial != loop->callback_list_serial) 699 goto next_iteration; 700 701 if (loop->depth != orig_depth) 702 goto next_iteration; 703 704 if (cb->type == CALLBACK_TIMEOUT && 705 dbus_timeout_get_enabled (TIMEOUT_CALLBACK (cb)->timeout)) 706 { 707 TimeoutCallback *tcb = TIMEOUT_CALLBACK (cb); 708 int msecs_remaining; 709 710 if (check_timeout (tv_sec, tv_usec, 711 tcb, &msecs_remaining)) 712 { 713 /* Save last callback time and fire this timeout */ 714 tcb->last_tv_sec = tv_sec; 715 tcb->last_tv_usec = tv_usec; 716 717#if MAINLOOP_SPEW 718 _dbus_verbose (" invoking timeout\n"); 719#endif 720 721 (* tcb->function) (tcb->timeout, 722 cb->data); 723 724 retval = TRUE; 725 } 726 else 727 { 728#if MAINLOOP_SPEW 729 _dbus_verbose (" timeout has not expired\n"); 730#endif 731 } 732 } 733#if MAINLOOP_SPEW 734 else if (cb->type == CALLBACK_TIMEOUT) 735 { 736 _dbus_verbose (" skipping invocation of disabled timeout\n"); 737 } 738#endif 739 740 link = next; 741 } 742 } 743 744 if (n_ready > 0) 745 { 746 i = 0; 747 while (i < n_fds) 748 { 749 /* FIXME I think this "restart if we change the watches" 750 * approach could result in starving watches 751 * toward the end of the list. 752 */ 753 if (initial_serial != loop->callback_list_serial) 754 goto next_iteration; 755 756 if (loop->depth != orig_depth) 757 goto next_iteration; 758 759 if (fds[i].revents != 0) 760 { 761 WatchCallback *wcb; 762 unsigned int condition; 763 764 wcb = watches_for_fds[i]; 765 766 condition = 0; 767 if (fds[i].revents & _DBUS_POLLIN) 768 condition |= DBUS_WATCH_READABLE; 769 if (fds[i].revents & _DBUS_POLLOUT) 770 condition |= DBUS_WATCH_WRITABLE; 771 if (fds[i].revents & _DBUS_POLLHUP) 772 condition |= DBUS_WATCH_HANGUP; 773 if (fds[i].revents & _DBUS_POLLERR) 774 condition |= DBUS_WATCH_ERROR; 775 776 /* condition may still be 0 if we got some 777 * weird POLLFOO thing like POLLWRBAND 778 */ 779 780 if (condition != 0 && 781 dbus_watch_get_enabled (wcb->watch)) 782 { 783 if (!(* wcb->function) (wcb->watch, 784 condition, 785 ((Callback*)wcb)->data)) 786 wcb->last_iteration_oom = TRUE; 787 788#if MAINLOOP_SPEW 789 _dbus_verbose (" Invoked watch, oom = %d\n", 790 wcb->last_iteration_oom); 791#endif 792 793 retval = TRUE; 794 } 795 } 796 797 ++i; 798 } 799 } 800 801 next_iteration: 802#if MAINLOOP_SPEW 803 _dbus_verbose (" moving to next iteration\n"); 804#endif 805 806 if (fds && fds != stack_fds) 807 dbus_free (fds); 808 if (watches_for_fds) 809 { 810 i = 0; 811 while (i < n_fds) 812 { 813 callback_unref (&watches_for_fds[i]->callback); 814 ++i; 815 } 816 817 if (watches_for_fds != stack_watches_for_fds) 818 dbus_free (watches_for_fds); 819 } 820 821 if (_dbus_loop_dispatch (loop)) 822 retval = TRUE; 823 824#if MAINLOOP_SPEW 825 _dbus_verbose ("Returning %d\n", retval); 826#endif 827 828 return retval; 829} 830 831void 832_dbus_loop_run (DBusLoop *loop) 833{ 834 int our_exit_depth; 835 836 _dbus_assert (loop->depth >= 0); 837 838 _dbus_loop_ref (loop); 839 840 our_exit_depth = loop->depth; 841 loop->depth += 1; 842 843 _dbus_verbose ("Running main loop, depth %d -> %d\n", 844 loop->depth - 1, loop->depth); 845 846 while (loop->depth != our_exit_depth) 847 _dbus_loop_iterate (loop, TRUE); 848 849 _dbus_loop_unref (loop); 850} 851 852void 853_dbus_loop_quit (DBusLoop *loop) 854{ 855 _dbus_assert (loop->depth > 0); 856 857 loop->depth -= 1; 858 859 _dbus_verbose ("Quit main loop, depth %d -> %d\n", 860 loop->depth + 1, loop->depth); 861} 862 863int 864_dbus_get_oom_wait (void) 865{ 866#ifdef DBUS_BUILD_TESTS 867 /* make tests go fast */ 868 return 0; 869#else 870 return 500; 871#endif 872} 873 874void 875_dbus_wait_for_memory (void) 876{ 877 _dbus_verbose ("Waiting for more memory\n"); 878 _dbus_sleep_milliseconds (_dbus_get_oom_wait ()); 879} 880 881#endif /* DOXYGEN_SHOULD_SKIP_THIS */ 882