Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

dbus-mainloop.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */ 00002 /* dbus-mainloop.c Main loop utility 00003 * 00004 * Copyright (C) 2003 Red Hat, Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00021 * 00022 */ 00023 00024 #include "dbus-mainloop.h" 00025 00026 #ifndef DOXYGEN_SHOULD_SKIP_THIS 00027 00028 #include <dbus/dbus-list.h> 00029 #include <dbus/dbus-sysdeps.h> 00030 00031 #define MAINLOOP_SPEW 0 00032 00033 struct DBusLoop 00034 { 00035 int refcount; 00036 DBusList *callbacks; 00037 int callback_list_serial; 00038 int watch_count; 00039 int timeout_count; 00040 int depth; 00041 DBusList *need_dispatch; 00042 }; 00043 00044 typedef enum 00045 { 00046 CALLBACK_WATCH, 00047 CALLBACK_TIMEOUT 00048 } CallbackType; 00049 00050 typedef struct 00051 { 00052 int refcount; 00053 CallbackType type; 00054 void *data; 00055 DBusFreeFunction free_data_func; 00056 } Callback; 00057 00058 typedef struct 00059 { 00060 Callback callback; 00061 DBusWatchFunction function; 00062 DBusWatch *watch; 00063 /* last watch handle failed due to OOM */ 00064 unsigned int last_iteration_oom : 1; 00065 } WatchCallback; 00066 00067 typedef struct 00068 { 00069 Callback callback; 00070 DBusTimeout *timeout; 00071 DBusTimeoutFunction function; 00072 unsigned long last_tv_sec; 00073 unsigned long last_tv_usec; 00074 } TimeoutCallback; 00075 00076 #define WATCH_CALLBACK(callback) ((WatchCallback*)callback) 00077 #define TIMEOUT_CALLBACK(callback) ((TimeoutCallback*)callback) 00078 00079 static WatchCallback* 00080 watch_callback_new (DBusWatch *watch, 00081 DBusWatchFunction function, 00082 void *data, 00083 DBusFreeFunction free_data_func) 00084 { 00085 WatchCallback *cb; 00086 00087 cb = dbus_new (WatchCallback, 1); 00088 if (cb == NULL) 00089 return NULL; 00090 00091 cb->watch = watch; 00092 cb->function = function; 00093 cb->last_iteration_oom = FALSE; 00094 cb->callback.refcount = 1; 00095 cb->callback.type = CALLBACK_WATCH; 00096 cb->callback.data = data; 00097 cb->callback.free_data_func = free_data_func; 00098 00099 return cb; 00100 } 00101 00102 static TimeoutCallback* 00103 timeout_callback_new (DBusTimeout *timeout, 00104 DBusTimeoutFunction function, 00105 void *data, 00106 DBusFreeFunction free_data_func) 00107 { 00108 TimeoutCallback *cb; 00109 00110 cb = dbus_new (TimeoutCallback, 1); 00111 if (cb == NULL) 00112 return NULL; 00113 00114 cb->timeout = timeout; 00115 cb->function = function; 00116 _dbus_get_current_time (&cb->last_tv_sec, 00117 &cb->last_tv_usec); 00118 cb->callback.refcount = 1; 00119 cb->callback.type = CALLBACK_TIMEOUT; 00120 cb->callback.data = data; 00121 cb->callback.free_data_func = free_data_func; 00122 00123 return cb; 00124 } 00125 00126 static Callback * 00127 callback_ref (Callback *cb) 00128 { 00129 _dbus_assert (cb->refcount > 0); 00130 00131 cb->refcount += 1; 00132 00133 return cb; 00134 } 00135 00136 static void 00137 callback_unref (Callback *cb) 00138 { 00139 _dbus_assert (cb->refcount > 0); 00140 00141 cb->refcount -= 1; 00142 00143 if (cb->refcount == 0) 00144 { 00145 if (cb->free_data_func) 00146 (* cb->free_data_func) (cb->data); 00147 00148 dbus_free (cb); 00149 } 00150 } 00151 00152 static dbus_bool_t 00153 add_callback (DBusLoop *loop, 00154 Callback *cb) 00155 { 00156 if (!_dbus_list_append (&loop->callbacks, cb)) 00157 return FALSE; 00158 00159 loop->callback_list_serial += 1; 00160 00161 switch (cb->type) 00162 { 00163 case CALLBACK_WATCH: 00164 loop->watch_count += 1; 00165 break; 00166 case CALLBACK_TIMEOUT: 00167 loop->timeout_count += 1; 00168 break; 00169 } 00170 00171 return TRUE; 00172 } 00173 00174 static void 00175 remove_callback (DBusLoop *loop, 00176 DBusList *link) 00177 { 00178 Callback *cb = link->data; 00179 00180 switch (cb->type) 00181 { 00182 case CALLBACK_WATCH: 00183 loop->watch_count -= 1; 00184 break; 00185 case CALLBACK_TIMEOUT: 00186 loop->timeout_count -= 1; 00187 break; 00188 } 00189 00190 callback_unref (cb); 00191 _dbus_list_remove_link (&loop->callbacks, link); 00192 loop->callback_list_serial += 1; 00193 } 00194 00195 DBusLoop* 00196 _dbus_loop_new (void) 00197 { 00198 DBusLoop *loop; 00199 00200 loop = dbus_new0 (DBusLoop, 1); 00201 if (loop == NULL) 00202 return NULL; 00203 00204 loop->refcount = 1; 00205 00206 return loop; 00207 } 00208 00209 DBusLoop * 00210 _dbus_loop_ref (DBusLoop *loop) 00211 { 00212 _dbus_assert (loop != NULL); 00213 _dbus_assert (loop->refcount > 0); 00214 00215 loop->refcount += 1; 00216 00217 return loop; 00218 } 00219 00220 void 00221 _dbus_loop_unref (DBusLoop *loop) 00222 { 00223 _dbus_assert (loop != NULL); 00224 _dbus_assert (loop->refcount > 0); 00225 00226 loop->refcount -= 1; 00227 if (loop->refcount == 0) 00228 { 00229 while (loop->need_dispatch) 00230 { 00231 DBusConnection *connection = _dbus_list_pop_first (&loop->need_dispatch); 00232 00233 dbus_connection_unref (connection); 00234 } 00235 00236 dbus_free (loop); 00237 } 00238 } 00239 00240 dbus_bool_t 00241 _dbus_loop_add_watch (DBusLoop *loop, 00242 DBusWatch *watch, 00243 DBusWatchFunction function, 00244 void *data, 00245 DBusFreeFunction free_data_func) 00246 { 00247 WatchCallback *wcb; 00248 00249 wcb = watch_callback_new (watch, function, data, free_data_func); 00250 if (wcb == NULL) 00251 return FALSE; 00252 00253 if (!add_callback (loop, (Callback*) wcb)) 00254 { 00255 wcb->callback.free_data_func = NULL; /* don't want to have this side effect */ 00256 callback_unref ((Callback*) wcb); 00257 return FALSE; 00258 } 00259 00260 return TRUE; 00261 } 00262 00263 void 00264 _dbus_loop_remove_watch (DBusLoop *loop, 00265 DBusWatch *watch, 00266 DBusWatchFunction function, 00267 void *data) 00268 { 00269 DBusList *link; 00270 00271 link = _dbus_list_get_first_link (&loop->callbacks); 00272 while (link != NULL) 00273 { 00274 DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); 00275 Callback *this = link->data; 00276 00277 if (this->type == CALLBACK_WATCH && 00278 WATCH_CALLBACK (this)->watch == watch && 00279 this->data == data && 00280 WATCH_CALLBACK (this)->function == function) 00281 { 00282 remove_callback (loop, link); 00283 00284 return; 00285 } 00286 00287 link = next; 00288 } 00289 00290 _dbus_warn ("could not find watch %p function %p data %p to remove\n", 00291 watch, (void *)function, data); 00292 } 00293 00294 dbus_bool_t 00295 _dbus_loop_add_timeout (DBusLoop *loop, 00296 DBusTimeout *timeout, 00297 DBusTimeoutFunction function, 00298 void *data, 00299 DBusFreeFunction free_data_func) 00300 { 00301 TimeoutCallback *tcb; 00302 00303 tcb = timeout_callback_new (timeout, function, data, free_data_func); 00304 if (tcb == NULL) 00305 return FALSE; 00306 00307 if (!add_callback (loop, (Callback*) tcb)) 00308 { 00309 tcb->callback.free_data_func = NULL; /* don't want to have this side effect */ 00310 callback_unref ((Callback*) tcb); 00311 return FALSE; 00312 } 00313 00314 return TRUE; 00315 } 00316 00317 void 00318 _dbus_loop_remove_timeout (DBusLoop *loop, 00319 DBusTimeout *timeout, 00320 DBusTimeoutFunction function, 00321 void *data) 00322 { 00323 DBusList *link; 00324 00325 link = _dbus_list_get_first_link (&loop->callbacks); 00326 while (link != NULL) 00327 { 00328 DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); 00329 Callback *this = link->data; 00330 00331 if (this->type == CALLBACK_TIMEOUT && 00332 TIMEOUT_CALLBACK (this)->timeout == timeout && 00333 this->data == data && 00334 TIMEOUT_CALLBACK (this)->function == function) 00335 { 00336 remove_callback (loop, link); 00337 00338 return; 00339 } 00340 00341 link = next; 00342 } 00343 00344 _dbus_warn ("could not find timeout %p function %p data %p to remove\n", 00345 timeout, (void *)function, data); 00346 } 00347 00348 /* Convolutions from GLib, there really must be a better way 00349 * to do this. 00350 */ 00351 static dbus_bool_t 00352 check_timeout (unsigned long tv_sec, 00353 unsigned long tv_usec, 00354 TimeoutCallback *tcb, 00355 int *timeout) 00356 { 00357 long sec_remaining; 00358 long msec_remaining; 00359 unsigned long expiration_tv_sec; 00360 unsigned long expiration_tv_usec; 00361 long interval_seconds; 00362 long interval_milliseconds; 00363 int interval; 00364 00365 /* I'm pretty sure this function could suck (a lot) less */ 00366 00367 interval = dbus_timeout_get_interval (tcb->timeout); 00368 00369 interval_seconds = interval / 1000L; 00370 interval_milliseconds = interval % 1000L; 00371 00372 expiration_tv_sec = tcb->last_tv_sec + interval_seconds; 00373 expiration_tv_usec = tcb->last_tv_usec + interval_milliseconds * 1000; 00374 if (expiration_tv_usec >= 1000000) 00375 { 00376 expiration_tv_usec -= 1000000; 00377 expiration_tv_sec += 1; 00378 } 00379 00380 sec_remaining = expiration_tv_sec - tv_sec; 00381 /* need to force this to be signed, as it is intended to sometimes 00382 * produce a negative result 00383 */ 00384 msec_remaining = ((long) expiration_tv_usec - (long) tv_usec) / 1000L; 00385 00386 #if MAINLOOP_SPEW 00387 _dbus_verbose ("Interval is %ld seconds %ld msecs\n", 00388 interval_seconds, 00389 interval_milliseconds); 00390 _dbus_verbose ("Now is %lu seconds %lu usecs\n", 00391 tv_sec, tv_usec); 00392 _dbus_verbose ("Last is %lu seconds %lu usecs\n", 00393 tcb->last_tv_sec, tcb->last_tv_usec); 00394 _dbus_verbose ("Exp is %lu seconds %lu usecs\n", 00395 expiration_tv_sec, expiration_tv_usec); 00396 _dbus_verbose ("Pre-correction, sec_remaining %ld msec_remaining %ld\n", 00397 sec_remaining, msec_remaining); 00398 #endif 00399 00400 /* We do the following in a rather convoluted fashion to deal with 00401 * the fact that we don't have an integral type big enough to hold 00402 * the difference of two timevals in milliseconds. 00403 */ 00404 if (sec_remaining < 0 || (sec_remaining == 0 && msec_remaining < 0)) 00405 { 00406 *timeout = 0; 00407 } 00408 else 00409 { 00410 if (msec_remaining < 0) 00411 { 00412 msec_remaining += 1000; 00413 sec_remaining -= 1; 00414 } 00415 00416 if (sec_remaining > (_DBUS_INT_MAX / 1000) || 00417 msec_remaining > _DBUS_INT_MAX) 00418 *timeout = _DBUS_INT_MAX; 00419 else 00420 *timeout = sec_remaining * 1000 + msec_remaining; 00421 } 00422 00423 if (*timeout > interval) 00424 { 00425 /* This indicates that the system clock probably moved backward */ 00426 _dbus_verbose ("System clock set backward! Resetting timeout.\n"); 00427 00428 tcb->last_tv_sec = tv_sec; 00429 tcb->last_tv_usec = tv_usec; 00430 00431 *timeout = interval; 00432 } 00433 00434 #if MAINLOOP_SPEW 00435 _dbus_verbose (" timeout expires in %d milliseconds\n", *timeout); 00436 #endif 00437 00438 return *timeout == 0; 00439 } 00440 00441 dbus_bool_t 00442 _dbus_loop_dispatch (DBusLoop *loop) 00443 { 00444 00445 #if MAINLOOP_SPEW 00446 _dbus_verbose (" %d connections to dispatch\n", _dbus_list_get_length (&loop->need_dispatch)); 00447 #endif 00448 00449 if (loop->need_dispatch == NULL) 00450 return FALSE; 00451 00452 next: 00453 while (loop->need_dispatch != NULL) 00454 { 00455 DBusConnection *connection = _dbus_list_pop_first (&loop->need_dispatch); 00456 00457 while (TRUE) 00458 { 00459 DBusDispatchStatus status; 00460 00461 status = dbus_connection_dispatch (connection); 00462 00463 if (status == DBUS_DISPATCH_COMPLETE) 00464 { 00465 dbus_connection_unref (connection); 00466 goto next; 00467 } 00468 else 00469 { 00470 if (status == DBUS_DISPATCH_NEED_MEMORY) 00471 _dbus_wait_for_memory (); 00472 } 00473 } 00474 } 00475 00476 return TRUE; 00477 } 00478 00479 dbus_bool_t 00480 _dbus_loop_queue_dispatch (DBusLoop *loop, 00481 DBusConnection *connection) 00482 { 00483 if (_dbus_list_append (&loop->need_dispatch, connection)) 00484 { 00485 dbus_connection_ref (connection); 00486 return TRUE; 00487 } 00488 else 00489 return FALSE; 00490 } 00491 00492 /* Returns TRUE if we invoked any timeouts or have ready file 00493 * descriptors, which is just used in test code as a debug hack 00494 */ 00495 00496 dbus_bool_t 00497 _dbus_loop_iterate (DBusLoop *loop, 00498 dbus_bool_t block) 00499 { 00500 #define N_STACK_DESCRIPTORS 64 00501 dbus_bool_t retval; 00502 DBusPollFD *fds; 00503 DBusPollFD stack_fds[N_STACK_DESCRIPTORS]; 00504 int n_fds; 00505 WatchCallback **watches_for_fds; 00506 WatchCallback *stack_watches_for_fds[N_STACK_DESCRIPTORS]; 00507 int i; 00508 DBusList *link; 00509 int n_ready; 00510 int initial_serial; 00511 long timeout; 00512 dbus_bool_t oom_watch_pending; 00513 int orig_depth; 00514 00515 retval = FALSE; 00516 00517 fds = NULL; 00518 watches_for_fds = NULL; 00519 n_fds = 0; 00520 oom_watch_pending = FALSE; 00521 orig_depth = loop->depth; 00522 00523 #if MAINLOOP_SPEW 00524 _dbus_verbose ("Iteration block=%d depth=%d timeout_count=%d watch_count=%d\n", 00525 block, loop->depth, loop->timeout_count, loop->watch_count); 00526 #endif 00527 00528 if (loop->callbacks == NULL) 00529 goto next_iteration; 00530 00531 if (loop->watch_count > N_STACK_DESCRIPTORS) 00532 { 00533 fds = dbus_new0 (DBusPollFD, loop->watch_count); 00534 00535 while (fds == NULL) 00536 { 00537 _dbus_wait_for_memory (); 00538 fds = dbus_new0 (DBusPollFD, loop->watch_count); 00539 } 00540 00541 watches_for_fds = dbus_new (WatchCallback*, loop->watch_count); 00542 while (watches_for_fds == NULL) 00543 { 00544 _dbus_wait_for_memory (); 00545 watches_for_fds = dbus_new (WatchCallback*, loop->watch_count); 00546 } 00547 } 00548 else 00549 { 00550 fds = stack_fds; 00551 watches_for_fds = stack_watches_for_fds; 00552 } 00553 00554 /* fill our array of fds and watches */ 00555 n_fds = 0; 00556 link = _dbus_list_get_first_link (&loop->callbacks); 00557 while (link != NULL) 00558 { 00559 DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); 00560 Callback *cb = link->data; 00561 if (cb->type == CALLBACK_WATCH) 00562 { 00563 unsigned int flags; 00564 WatchCallback *wcb = WATCH_CALLBACK (cb); 00565 00566 if (wcb->last_iteration_oom) 00567 { 00568 /* we skip this one this time, but reenable it next time, 00569 * and have a timeout on this iteration 00570 */ 00571 wcb->last_iteration_oom = FALSE; 00572 oom_watch_pending = TRUE; 00573 00574 retval = TRUE; /* return TRUE here to keep the loop going, 00575 * since we don't know the watch is inactive 00576 */ 00577 00578 #if MAINLOOP_SPEW 00579 _dbus_verbose (" skipping watch on fd %d as it was out of memory last time\n", 00580 dbus_watch_get_fd (wcb->watch)); 00581 #endif 00582 } 00583 else if (dbus_watch_get_enabled (wcb->watch)) 00584 { 00585 watches_for_fds[n_fds] = wcb; 00586 00587 callback_ref (cb); 00588 00589 flags = dbus_watch_get_flags (wcb->watch); 00590 00591 fds[n_fds].fd = dbus_watch_get_fd (wcb->watch); 00592 fds[n_fds].revents = 0; 00593 fds[n_fds].events = 0; 00594 if (flags & DBUS_WATCH_READABLE) 00595 fds[n_fds].events |= _DBUS_POLLIN; 00596 if (flags & DBUS_WATCH_WRITABLE) 00597 fds[n_fds].events |= _DBUS_POLLOUT; 00598 00599 #if MAINLOOP_SPEW 00600 _dbus_verbose (" polling watch on fd %d\n", fds[n_fds].fd); 00601 #endif 00602 00603 n_fds += 1; 00604 } 00605 else 00606 { 00607 #if MAINLOOP_SPEW 00608 _dbus_verbose (" skipping disabled watch on fd %d\n", 00609 dbus_watch_get_fd (wcb->watch)); 00610 #endif 00611 } 00612 } 00613 00614 link = next; 00615 } 00616 00617 timeout = -1; 00618 if (loop->timeout_count > 0) 00619 { 00620 unsigned long tv_sec; 00621 unsigned long tv_usec; 00622 00623 _dbus_get_current_time (&tv_sec, &tv_usec); 00624 00625 link = _dbus_list_get_first_link (&loop->callbacks); 00626 while (link != NULL) 00627 { 00628 DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); 00629 Callback *cb = link->data; 00630 00631 if (cb->type == CALLBACK_TIMEOUT && 00632 dbus_timeout_get_enabled (TIMEOUT_CALLBACK (cb)->timeout)) 00633 { 00634 TimeoutCallback *tcb = TIMEOUT_CALLBACK (cb); 00635 int msecs_remaining; 00636 00637 check_timeout (tv_sec, tv_usec, tcb, &msecs_remaining); 00638 00639 if (timeout < 0) 00640 timeout = msecs_remaining; 00641 else 00642 timeout = MIN (msecs_remaining, timeout); 00643 00644 #if MAINLOOP_SPEW 00645 _dbus_verbose (" timeout added, %d remaining, aggregate timeout %ld\n", 00646 msecs_remaining, timeout); 00647 #endif 00648 00649 _dbus_assert (timeout >= 0); 00650 00651 if (timeout == 0) 00652 break; /* it's not going to get shorter... */ 00653 } 00654 #if MAINLOOP_SPEW 00655 else if (cb->type == CALLBACK_TIMEOUT) 00656 { 00657 _dbus_verbose (" skipping disabled timeout\n"); 00658 } 00659 #endif 00660 00661 link = next; 00662 } 00663 } 00664 00665 /* Never block if we have stuff to dispatch */ 00666 if (!block || loop->need_dispatch != NULL) 00667 { 00668 timeout = 0; 00669 #if MAINLOOP_SPEW 00670 _dbus_verbose (" timeout is 0 as we aren't blocking\n"); 00671 #endif 00672 } 00673 00674 /* if a watch is OOM, don't wait longer than the OOM 00675 * wait to re-enable it 00676 */ 00677 if (oom_watch_pending) 00678 timeout = MIN (timeout, _dbus_get_oom_wait ()); 00679 00680 #if MAINLOOP_SPEW 00681 _dbus_verbose (" polling on %d descriptors timeout %ld\n", n_fds, timeout); 00682 #endif 00683 00684 n_ready = _dbus_poll (fds, n_fds, timeout); 00685 00686 initial_serial = loop->callback_list_serial; 00687 00688 if (loop->timeout_count > 0) 00689 { 00690 unsigned long tv_sec; 00691 unsigned long tv_usec; 00692 00693 _dbus_get_current_time (&tv_sec, &tv_usec); 00694 00695 /* It'd be nice to avoid this O(n) thingy here */ 00696 link = _dbus_list_get_first_link (&loop->callbacks); 00697 while (link != NULL) 00698 { 00699 DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); 00700 Callback *cb = link->data; 00701 00702 if (initial_serial != loop->callback_list_serial) 00703 goto next_iteration; 00704 00705 if (loop->depth != orig_depth) 00706 goto next_iteration; 00707 00708 if (cb->type == CALLBACK_TIMEOUT && 00709 dbus_timeout_get_enabled (TIMEOUT_CALLBACK (cb)->timeout)) 00710 { 00711 TimeoutCallback *tcb = TIMEOUT_CALLBACK (cb); 00712 int msecs_remaining; 00713 00714 if (check_timeout (tv_sec, tv_usec, 00715 tcb, &msecs_remaining)) 00716 { 00717 /* Save last callback time and fire this timeout */ 00718 tcb->last_tv_sec = tv_sec; 00719 tcb->last_tv_usec = tv_usec; 00720 00721 #if MAINLOOP_SPEW 00722 _dbus_verbose (" invoking timeout\n"); 00723 #endif 00724 00725 (* tcb->function) (tcb->timeout, 00726 cb->data); 00727 00728 retval = TRUE; 00729 } 00730 else 00731 { 00732 #if MAINLOOP_SPEW 00733 _dbus_verbose (" timeout has not expired\n"); 00734 #endif 00735 } 00736 } 00737 #if MAINLOOP_SPEW 00738 else if (cb->type == CALLBACK_TIMEOUT) 00739 { 00740 _dbus_verbose (" skipping invocation of disabled timeout\n"); 00741 } 00742 #endif 00743 00744 link = next; 00745 } 00746 } 00747 00748 if (n_ready > 0) 00749 { 00750 i = 0; 00751 while (i < n_fds) 00752 { 00753 /* FIXME I think this "restart if we change the watches" 00754 * approach could result in starving watches 00755 * toward the end of the list. 00756 */ 00757 if (initial_serial != loop->callback_list_serial) 00758 goto next_iteration; 00759 00760 if (loop->depth != orig_depth) 00761 goto next_iteration; 00762 00763 if (fds[i].revents != 0) 00764 { 00765 WatchCallback *wcb; 00766 unsigned int condition; 00767 00768 wcb = watches_for_fds[i]; 00769 00770 condition = 0; 00771 if (fds[i].revents & _DBUS_POLLIN) 00772 condition |= DBUS_WATCH_READABLE; 00773 if (fds[i].revents & _DBUS_POLLOUT) 00774 condition |= DBUS_WATCH_WRITABLE; 00775 if (fds[i].revents & _DBUS_POLLHUP) 00776 condition |= DBUS_WATCH_HANGUP; 00777 if (fds[i].revents & _DBUS_POLLERR) 00778 condition |= DBUS_WATCH_ERROR; 00779 00780 /* condition may still be 0 if we got some 00781 * weird POLLFOO thing like POLLWRBAND 00782 */ 00783 00784 if (condition != 0 && 00785 dbus_watch_get_enabled (wcb->watch)) 00786 { 00787 if (!(* wcb->function) (wcb->watch, 00788 condition, 00789 ((Callback*)wcb)->data)) 00790 wcb->last_iteration_oom = TRUE; 00791 00792 #if MAINLOOP_SPEW 00793 _dbus_verbose (" Invoked watch, oom = %d\n", 00794 wcb->last_iteration_oom); 00795 #endif 00796 00797 retval = TRUE; 00798 } 00799 } 00800 00801 ++i; 00802 } 00803 } 00804 00805 next_iteration: 00806 #if MAINLOOP_SPEW 00807 _dbus_verbose (" moving to next iteration\n"); 00808 #endif 00809 00810 if (fds && fds != stack_fds) 00811 dbus_free (fds); 00812 if (watches_for_fds) 00813 { 00814 i = 0; 00815 while (i < n_fds) 00816 { 00817 callback_unref (&watches_for_fds[i]->callback); 00818 ++i; 00819 } 00820 00821 if (watches_for_fds != stack_watches_for_fds) 00822 dbus_free (watches_for_fds); 00823 } 00824 00825 if (_dbus_loop_dispatch (loop)) 00826 retval = TRUE; 00827 00828 #if MAINLOOP_SPEW 00829 _dbus_verbose ("Returning %d\n", retval); 00830 #endif 00831 00832 return retval; 00833 } 00834 00835 void 00836 _dbus_loop_run (DBusLoop *loop) 00837 { 00838 int our_exit_depth; 00839 00840 _dbus_assert (loop->depth >= 0); 00841 00842 _dbus_loop_ref (loop); 00843 00844 our_exit_depth = loop->depth; 00845 loop->depth += 1; 00846 00847 _dbus_verbose ("Running main loop, depth %d -> %d\n", 00848 loop->depth - 1, loop->depth); 00849 00850 while (loop->depth != our_exit_depth) 00851 _dbus_loop_iterate (loop, TRUE); 00852 00853 _dbus_loop_unref (loop); 00854 } 00855 00856 void 00857 _dbus_loop_quit (DBusLoop *loop) 00858 { 00859 _dbus_assert (loop->depth > 0); 00860 00861 loop->depth -= 1; 00862 00863 _dbus_verbose ("Quit main loop, depth %d -> %d\n", 00864 loop->depth + 1, loop->depth); 00865 } 00866 00867 int 00868 _dbus_get_oom_wait (void) 00869 { 00870 #ifdef DBUS_BUILD_TESTS 00871 /* make tests go fast */ 00872 return 0; 00873 #else 00874 return 500; 00875 #endif 00876 } 00877 00878 void 00879 _dbus_wait_for_memory (void) 00880 { 00881 _dbus_verbose ("Waiting for more memory\n"); 00882 _dbus_sleep_milliseconds (_dbus_get_oom_wait ()); 00883 } 00884 00885 #endif /* DOXYGEN_SHOULD_SKIP_THIS */

Generated on Mon Aug 16 17:40:08 2004 for D-BUS by doxygen 1.3.8