00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
#include "dbus-internals.h"
00025
#include "dbus-watch.h"
00026
#include "dbus-list.h"
00027
00039 struct DBusWatch
00040 {
00041 int refcount;
00042 int fd;
00043 unsigned int flags;
00045 DBusWatchHandler
handler;
00046 void *
handler_data;
00047 DBusFreeFunction free_handler_data_function;
00049 void *
data;
00050 DBusFreeFunction free_data_function;
00051 unsigned int enabled : 1;
00052 };
00053
00066
DBusWatch*
00067 _dbus_watch_new (
int fd,
00068
unsigned int flags,
00069
dbus_bool_t enabled,
00070 DBusWatchHandler handler,
00071
void *data,
00072
DBusFreeFunction free_data_function)
00073 {
00074
DBusWatch *watch;
00075
00076
#define VALID_WATCH_FLAGS (DBUS_WATCH_WRITABLE | DBUS_WATCH_READABLE)
00077
00078
_dbus_assert ((flags & VALID_WATCH_FLAGS) == flags);
00079
00080 watch =
dbus_new0 (
DBusWatch, 1);
00081
if (watch ==
NULL)
00082
return NULL;
00083
00084 watch->
refcount = 1;
00085 watch->
fd = fd;
00086 watch->
flags = flags;
00087 watch->
enabled = enabled;
00088
00089 watch->
handler = handler;
00090 watch->
handler_data = data;
00091 watch->
free_handler_data_function = free_data_function;
00092
00093
return watch;
00094 }
00095
00102
DBusWatch *
00103 _dbus_watch_ref (
DBusWatch *watch)
00104 {
00105 watch->
refcount += 1;
00106
00107
return watch;
00108 }
00109
00116
void
00117 _dbus_watch_unref (
DBusWatch *watch)
00118 {
00119
_dbus_assert (watch !=
NULL);
00120
_dbus_assert (watch->
refcount > 0);
00121
00122 watch->
refcount -= 1;
00123
if (watch->
refcount == 0)
00124 {
00125
dbus_watch_set_data (watch,
NULL,
NULL);
00126
00127
if (watch->
free_handler_data_function)
00128 (* watch->
free_handler_data_function) (watch->
handler_data);
00129
00130
dbus_free (watch);
00131 }
00132 }
00133
00144
void
00145 _dbus_watch_invalidate (
DBusWatch *watch)
00146 {
00147 watch->
fd = -1;
00148 watch->
flags = 0;
00149 }
00150
00160
void
00161 _dbus_watch_sanitize_condition (
DBusWatch *watch,
00162
unsigned int *condition)
00163 {
00164
if (!(watch->
flags & DBUS_WATCH_READABLE))
00165 *condition &= ~DBUS_WATCH_READABLE;
00166
if (!(watch->
flags & DBUS_WATCH_WRITABLE))
00167 *condition &= ~DBUS_WATCH_WRITABLE;
00168 }
00169
00170
00190 struct DBusWatchList
00191 {
00192 DBusList *
watches;
00194 DBusAddWatchFunction
add_watch_function;
00195 DBusRemoveWatchFunction
remove_watch_function;
00196 DBusWatchToggledFunction
watch_toggled_function;
00197 void *
watch_data;
00198 DBusFreeFunction watch_free_data_function;
00199 };
00200
00207
DBusWatchList*
00208 _dbus_watch_list_new (
void)
00209 {
00210
DBusWatchList *watch_list;
00211
00212 watch_list =
dbus_new0 (
DBusWatchList, 1);
00213
if (watch_list ==
NULL)
00214
return NULL;
00215
00216
return watch_list;
00217 }
00218
00224
void
00225 _dbus_watch_list_free (
DBusWatchList *watch_list)
00226 {
00227
00228
_dbus_watch_list_set_functions (watch_list,
00229
NULL,
NULL,
NULL,
NULL,
NULL);
00230
_dbus_list_foreach (&watch_list->
watches,
00231 (
DBusForeachFunction)
_dbus_watch_unref,
00232
NULL);
00233
_dbus_list_clear (&watch_list->
watches);
00234
00235
dbus_free (watch_list);
00236 }
00237
00252
dbus_bool_t
00253 _dbus_watch_list_set_functions (
DBusWatchList *watch_list,
00254 DBusAddWatchFunction add_function,
00255 DBusRemoveWatchFunction remove_function,
00256 DBusWatchToggledFunction toggled_function,
00257
void *data,
00258
DBusFreeFunction free_data_function)
00259 {
00260
00261
if (add_function !=
NULL)
00262 {
00263
DBusList *link;
00264
00265 link =
_dbus_list_get_first_link (&watch_list->
watches);
00266
while (link !=
NULL)
00267 {
00268
DBusList *next =
_dbus_list_get_next_link (&watch_list->
watches,
00269 link);
00270
00271 _dbus_verbose (
"Adding a watch on fd %d using newly-set add watch function\n",
00272
dbus_watch_get_fd (link->
data));
00273
00274
if (!(* add_function) (link->
data, data))
00275 {
00276
00277
DBusList *link2;
00278
00279 link2 =
_dbus_list_get_first_link (&watch_list->
watches);
00280
while (link2 != link)
00281 {
00282
DBusList *next =
_dbus_list_get_next_link (&watch_list->
watches,
00283 link2);
00284
00285 _dbus_verbose (
"Removing watch on fd %d using newly-set remove function because initial add failed\n",
00286
dbus_watch_get_fd (link2->
data));
00287
00288 (* remove_function) (link2->
data, data);
00289
00290 link2 = next;
00291 }
00292
00293
return FALSE;
00294 }
00295
00296 link = next;
00297 }
00298 }
00299
00300
00301
00302
if (watch_list->
remove_watch_function !=
NULL)
00303 {
00304 _dbus_verbose (
"Removing all pre-existing watches\n");
00305
00306
_dbus_list_foreach (&watch_list->
watches,
00307 (
DBusForeachFunction) watch_list->
remove_watch_function,
00308 watch_list->
watch_data);
00309 }
00310
00311
if (watch_list->
watch_free_data_function !=
NULL)
00312 (* watch_list->
watch_free_data_function) (watch_list->
watch_data);
00313
00314 watch_list->
add_watch_function = add_function;
00315 watch_list->
remove_watch_function = remove_function;
00316 watch_list->
watch_toggled_function = toggled_function;
00317 watch_list->
watch_data = data;
00318 watch_list->
watch_free_data_function = free_data_function;
00319
00320
return TRUE;
00321 }
00322
00331
dbus_bool_t
00332 _dbus_watch_list_add_watch (
DBusWatchList *watch_list,
00333
DBusWatch *watch)
00334 {
00335
if (!
_dbus_list_append (&watch_list->
watches, watch))
00336
return FALSE;
00337
00338
_dbus_watch_ref (watch);
00339
00340
if (watch_list->
add_watch_function !=
NULL)
00341 {
00342 _dbus_verbose (
"Adding watch on fd %d\n",
00343
dbus_watch_get_fd (watch));
00344
00345
if (!(* watch_list->
add_watch_function) (watch,
00346 watch_list->
watch_data))
00347 {
00348
_dbus_list_remove_last (&watch_list->
watches, watch);
00349
_dbus_watch_unref (watch);
00350
return FALSE;
00351 }
00352 }
00353
00354
return TRUE;
00355 }
00356
00364
void
00365 _dbus_watch_list_remove_watch (
DBusWatchList *watch_list,
00366
DBusWatch *watch)
00367 {
00368
if (!
_dbus_list_remove (&watch_list->
watches, watch))
00369
_dbus_assert_not_reached (
"Nonexistent watch was removed");
00370
00371
if (watch_list->
remove_watch_function !=
NULL)
00372 {
00373 _dbus_verbose (
"Removing watch on fd %d\n",
00374
dbus_watch_get_fd (watch));
00375
00376 (* watch_list->
remove_watch_function) (watch,
00377 watch_list->
watch_data);
00378 }
00379
00380
_dbus_watch_unref (watch);
00381 }
00382
00391
void
00392 _dbus_watch_list_toggle_watch (
DBusWatchList *watch_list,
00393
DBusWatch *watch,
00394
dbus_bool_t enabled)
00395 {
00396 enabled = !!enabled;
00397
00398
if (enabled == watch->
enabled)
00399
return;
00400
00401 watch->
enabled = enabled;
00402
00403
if (watch_list->
watch_toggled_function !=
NULL)
00404 {
00405 _dbus_verbose (
"Toggling watch on fd %d to %d\n",
00406
dbus_watch_get_fd (watch), watch->enabled);
00407
00408 (* watch_list->
watch_toggled_function) (watch,
00409 watch_list->
watch_data);
00410 }
00411 }
00412
00425
void
00426 _dbus_watch_set_handler (
DBusWatch *watch,
00427 DBusWatchHandler handler,
00428
void *data,
00429
DBusFreeFunction free_data_function)
00430 {
00431
if (watch->
free_handler_data_function)
00432 (* watch->
free_handler_data_function) (watch->
handler_data);
00433
00434 watch->
handler = handler;
00435 watch->
handler_data = data;
00436 watch->
free_handler_data_function = free_data_function;
00437 }
00438
00467
int
00468 dbus_watch_get_fd (
DBusWatch *watch)
00469 {
00470
return watch->
fd;
00471 }
00472
00486
unsigned int
00487 dbus_watch_get_flags (
DBusWatch *watch)
00488 {
00489
_dbus_assert ((watch->
flags & VALID_WATCH_FLAGS) == watch->
flags);
00490
00491
return watch->
flags;
00492 }
00493
00501
void*
00502 dbus_watch_get_data (
DBusWatch *watch)
00503 {
00504
return watch->
data;
00505 }
00506
00518
void
00519 dbus_watch_set_data (
DBusWatch *watch,
00520
void *data,
00521
DBusFreeFunction free_data_function)
00522 {
00523 _dbus_verbose (
"Setting watch fd %d data to data = %p function = %p from data = %p function = %p\n",
00524
dbus_watch_get_fd (watch),
00525 data, free_data_function, watch->data, watch->free_data_function);
00526
00527
if (watch->free_data_function !=
NULL)
00528 (* watch->free_data_function) (watch->data);
00529
00530 watch->data = data;
00531 watch->free_data_function = free_data_function;
00532 }
00533
00541
dbus_bool_t
00542 dbus_watch_get_enabled (
DBusWatch *watch)
00543 {
00544
_dbus_assert (watch !=
NULL);
00545
return watch->
enabled;
00546 }
00547
00548
00571
dbus_bool_t
00572 dbus_watch_handle (
DBusWatch *watch,
00573
unsigned int flags)
00574 {
00575
#ifndef DBUS_DISABLE_CHECKS
00576
if (watch->
fd < 0 || watch->
flags == 0)
00577 {
00578
_dbus_warn (
"%s: Watch is invalid, it should have been removed\n",
00579 _DBUS_FUNCTION_NAME);
00580
return TRUE;
00581 }
00582
#endif
00583
00584 _dbus_return_val_if_fail (watch->
fd >= 0 ,
TRUE);
00585
00586
_dbus_watch_sanitize_condition (watch, &flags);
00587
00588
if (flags == 0)
00589 {
00590 _dbus_verbose (
"After sanitization, watch flags on fd %d were 0\n",
00591 watch->
fd);
00592
return TRUE;
00593 }
00594
else
00595
return (* watch->
handler) (watch, flags,
00596 watch->
handler_data);
00597 }
00598
00599