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