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