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
00036 struct DBusWatch
00037 {
00038 int refcount;
00039 int fd;
00040 unsigned int flags;
00042 DBusWatchHandler handler;
00043 void *handler_data;
00044 DBusFreeFunction free_handler_data_function;
00046 void *data;
00047 DBusFreeFunction free_data_function;
00048 unsigned int enabled : 1;
00049 };
00050
00063 DBusWatch*
00064 _dbus_watch_new (int fd,
00065 unsigned int flags,
00066 dbus_bool_t enabled,
00067 DBusWatchHandler handler,
00068 void *data,
00069 DBusFreeFunction free_data_function)
00070 {
00071 DBusWatch *watch;
00072
00073 #define VALID_WATCH_FLAGS (DBUS_WATCH_WRITABLE | DBUS_WATCH_READABLE)
00074
00075 _dbus_assert ((flags & VALID_WATCH_FLAGS) == flags);
00076
00077 watch = dbus_new0 (DBusWatch, 1);
00078 if (watch == NULL)
00079 return NULL;
00080
00081 watch->refcount = 1;
00082 watch->fd = fd;
00083 watch->flags = flags;
00084 watch->enabled = enabled;
00085
00086 watch->handler = handler;
00087 watch->handler_data = data;
00088 watch->free_handler_data_function = free_data_function;
00089
00090 return watch;
00091 }
00092
00098 void
00099 _dbus_watch_ref (DBusWatch *watch)
00100 {
00101 watch->refcount += 1;
00102 }
00103
00110 void
00111 _dbus_watch_unref (DBusWatch *watch)
00112 {
00113 _dbus_assert (watch != NULL);
00114 _dbus_assert (watch->refcount > 0);
00115
00116 watch->refcount -= 1;
00117 if (watch->refcount == 0)
00118 {
00119 dbus_watch_set_data (watch, NULL, NULL);
00120
00121 if (watch->free_handler_data_function)
00122 (* watch->free_handler_data_function) (watch->handler_data);
00123
00124 dbus_free (watch);
00125 }
00126 }
00127
00138 void
00139 _dbus_watch_invalidate (DBusWatch *watch)
00140 {
00141 watch->fd = -1;
00142 watch->flags = 0;
00143 }
00144
00154 void
00155 _dbus_watch_sanitize_condition (DBusWatch *watch,
00156 unsigned int *condition)
00157 {
00158 if (!(watch->flags & DBUS_WATCH_READABLE))
00159 *condition &= ~DBUS_WATCH_READABLE;
00160 if (!(watch->flags & DBUS_WATCH_WRITABLE))
00161 *condition &= ~DBUS_WATCH_WRITABLE;
00162 }
00163
00164
00184 struct DBusWatchList
00185 {
00186 DBusList *watches;
00188 DBusAddWatchFunction add_watch_function;
00189 DBusRemoveWatchFunction remove_watch_function;
00190 DBusWatchToggledFunction watch_toggled_function;
00191 void *watch_data;
00192 DBusFreeFunction watch_free_data_function;
00193 };
00194
00201 DBusWatchList*
00202 _dbus_watch_list_new (void)
00203 {
00204 DBusWatchList *watch_list;
00205
00206 watch_list = dbus_new0 (DBusWatchList, 1);
00207 if (watch_list == NULL)
00208 return NULL;
00209
00210 return watch_list;
00211 }
00212
00218 void
00219 _dbus_watch_list_free (DBusWatchList *watch_list)
00220 {
00221
00222 _dbus_watch_list_set_functions (watch_list,
00223 NULL, NULL, NULL, NULL, NULL);
00224 _dbus_list_foreach (&watch_list->watches,
00225 (DBusForeachFunction) _dbus_watch_unref,
00226 NULL);
00227 _dbus_list_clear (&watch_list->watches);
00228
00229 dbus_free (watch_list);
00230 }
00231
00246 dbus_bool_t
00247 _dbus_watch_list_set_functions (DBusWatchList *watch_list,
00248 DBusAddWatchFunction add_function,
00249 DBusRemoveWatchFunction remove_function,
00250 DBusWatchToggledFunction toggled_function,
00251 void *data,
00252 DBusFreeFunction free_data_function)
00253 {
00254
00255 if (add_function != NULL)
00256 {
00257 DBusList *link;
00258
00259 link = _dbus_list_get_first_link (&watch_list->watches);
00260 while (link != NULL)
00261 {
00262 DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
00263 link);
00264
00265 _dbus_verbose ("Adding a watch on fd %d using newly-set add watch function\n",
00266 dbus_watch_get_fd (link->data));
00267
00268 if (!(* add_function) (link->data, data))
00269 {
00270
00271 DBusList *link2;
00272
00273 link2 = _dbus_list_get_first_link (&watch_list->watches);
00274 while (link2 != link)
00275 {
00276 DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
00277 link2);
00278
00279 _dbus_verbose ("Removing watch on fd %d using newly-set remove function because initial add failed\n",
00280 dbus_watch_get_fd (link2->data));
00281
00282 (* remove_function) (link2->data, data);
00283
00284 link2 = next;
00285 }
00286
00287 return FALSE;
00288 }
00289
00290 link = next;
00291 }
00292 }
00293
00294
00295
00296 if (watch_list->remove_watch_function != NULL)
00297 {
00298 _dbus_verbose ("Removing all pre-existing watches\n");
00299
00300 _dbus_list_foreach (&watch_list->watches,
00301 (DBusForeachFunction) watch_list->remove_watch_function,
00302 watch_list->watch_data);
00303 }
00304
00305 if (watch_list->watch_free_data_function != NULL)
00306 (* watch_list->watch_free_data_function) (watch_list->watch_data);
00307
00308 watch_list->add_watch_function = add_function;
00309 watch_list->remove_watch_function = remove_function;
00310 watch_list->watch_toggled_function = toggled_function;
00311 watch_list->watch_data = data;
00312 watch_list->watch_free_data_function = free_data_function;
00313
00314 return TRUE;
00315 }
00316
00325 dbus_bool_t
00326 _dbus_watch_list_add_watch (DBusWatchList *watch_list,
00327 DBusWatch *watch)
00328 {
00329 if (!_dbus_list_append (&watch_list->watches, watch))
00330 return FALSE;
00331
00332 _dbus_watch_ref (watch);
00333
00334 if (watch_list->add_watch_function != NULL)
00335 {
00336 _dbus_verbose ("Adding watch on fd %d\n",
00337 dbus_watch_get_fd (watch));
00338
00339 if (!(* watch_list->add_watch_function) (watch,
00340 watch_list->watch_data))
00341 {
00342 _dbus_list_remove_last (&watch_list->watches, watch);
00343 _dbus_watch_unref (watch);
00344 return FALSE;
00345 }
00346 }
00347
00348 return TRUE;
00349 }
00350
00358 void
00359 _dbus_watch_list_remove_watch (DBusWatchList *watch_list,
00360 DBusWatch *watch)
00361 {
00362 if (!_dbus_list_remove (&watch_list->watches, watch))
00363 _dbus_assert_not_reached ("Nonexistent watch was removed");
00364
00365 if (watch_list->remove_watch_function != NULL)
00366 {
00367 _dbus_verbose ("Removing watch on fd %d\n",
00368 dbus_watch_get_fd (watch));
00369
00370 (* watch_list->remove_watch_function) (watch,
00371 watch_list->watch_data);
00372 }
00373
00374 _dbus_watch_unref (watch);
00375 }
00376
00385 void
00386 _dbus_watch_list_toggle_watch (DBusWatchList *watch_list,
00387 DBusWatch *watch,
00388 dbus_bool_t enabled)
00389 {
00390 enabled = !!enabled;
00391
00392 if (enabled == watch->enabled)
00393 return;
00394
00395 watch->enabled = enabled;
00396
00397 if (watch_list->watch_toggled_function != NULL)
00398 {
00399 _dbus_verbose ("Toggling watch on fd %d to %d\n",
00400 dbus_watch_get_fd (watch), watch->enabled);
00401
00402 (* watch_list->watch_toggled_function) (watch,
00403 watch_list->watch_data);
00404 }
00405 }
00406
00419 void
00420 _dbus_watch_set_handler (DBusWatch *watch,
00421 DBusWatchHandler handler,
00422 void *data,
00423 DBusFreeFunction free_data_function)
00424 {
00425 if (watch->free_handler_data_function)
00426 (* watch->free_handler_data_function) (watch->handler_data);
00427
00428 watch->handler = handler;
00429 watch->handler_data = data;
00430 watch->free_handler_data_function = free_data_function;
00431 }
00432
00461 int
00462 dbus_watch_get_fd (DBusWatch *watch)
00463 {
00464 return watch->fd;
00465 }
00466
00480 unsigned int
00481 dbus_watch_get_flags (DBusWatch *watch)
00482 {
00483 _dbus_assert ((watch->flags & VALID_WATCH_FLAGS) == watch->flags);
00484
00485 return watch->flags;
00486 }
00487
00495 void*
00496 dbus_watch_get_data (DBusWatch *watch)
00497 {
00498 return watch->data;
00499 }
00500
00512 void
00513 dbus_watch_set_data (DBusWatch *watch,
00514 void *data,
00515 DBusFreeFunction free_data_function)
00516 {
00517 _dbus_verbose ("Setting watch fd %d data to data = %p function = %p from data = %p function = %p\n",
00518 dbus_watch_get_fd (watch),
00519 data, free_data_function, watch->data, watch->free_data_function);
00520
00521 if (watch->free_data_function != NULL)
00522 (* watch->free_data_function) (watch->data);
00523
00524 watch->data = data;
00525 watch->free_data_function = free_data_function;
00526 }
00527
00535 dbus_bool_t
00536 dbus_watch_get_enabled (DBusWatch *watch)
00537 {
00538 _dbus_assert (watch != NULL);
00539 return watch->enabled;
00540 }
00541
00542
00565 dbus_bool_t
00566 dbus_watch_handle (DBusWatch *watch,
00567 unsigned int flags)
00568 {
00569 #ifndef DBUS_DISABLE_CHECKS
00570 if (watch->fd < 0 || watch->flags == 0)
00571 {
00572 _dbus_warn ("%s: Watch is invalid, it should have been removed\n",
00573 _DBUS_FUNCTION_NAME);
00574 return TRUE;
00575 }
00576 #endif
00577
00578 _dbus_return_val_if_fail (watch->fd >= 0 , TRUE);
00579
00580 _dbus_watch_sanitize_condition (watch, &flags);
00581
00582 if (flags == 0)
00583 {
00584 _dbus_verbose ("After sanitization, watch flags on fd %d were 0\n",
00585 watch->fd);
00586 return TRUE;
00587 }
00588 else
00589 return (* watch->handler) (watch, flags,
00590 watch->handler_data);
00591 }
00592
00593