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
00101 void
00102 _dbus_watch_ref (DBusWatch *watch)
00103 {
00104 watch->refcount += 1;
00105 }
00106
00113 void
00114 _dbus_watch_unref (DBusWatch *watch)
00115 {
00116 _dbus_assert (watch != NULL);
00117 _dbus_assert (watch->refcount > 0);
00118
00119 watch->refcount -= 1;
00120 if (watch->refcount == 0)
00121 {
00122 dbus_watch_set_data (watch, NULL, NULL);
00123
00124 if (watch->free_handler_data_function)
00125 (* watch->free_handler_data_function) (watch->handler_data);
00126
00127 dbus_free (watch);
00128 }
00129 }
00130
00141 void
00142 _dbus_watch_invalidate (DBusWatch *watch)
00143 {
00144 watch->fd = -1;
00145 watch->flags = 0;
00146 }
00147
00157 void
00158 _dbus_watch_sanitize_condition (DBusWatch *watch,
00159 unsigned int *condition)
00160 {
00161 if (!(watch->flags & DBUS_WATCH_READABLE))
00162 *condition &= ~DBUS_WATCH_READABLE;
00163 if (!(watch->flags & DBUS_WATCH_WRITABLE))
00164 *condition &= ~DBUS_WATCH_WRITABLE;
00165 }
00166
00167
00187 struct DBusWatchList
00188 {
00189 DBusList *watches;
00191 DBusAddWatchFunction add_watch_function;
00192 DBusRemoveWatchFunction remove_watch_function;
00193 DBusWatchToggledFunction watch_toggled_function;
00194 void *watch_data;
00195 DBusFreeFunction watch_free_data_function;
00196 };
00197
00204 DBusWatchList*
00205 _dbus_watch_list_new (void)
00206 {
00207 DBusWatchList *watch_list;
00208
00209 watch_list = dbus_new0 (DBusWatchList, 1);
00210 if (watch_list == NULL)
00211 return NULL;
00212
00213 return watch_list;
00214 }
00215
00221 void
00222 _dbus_watch_list_free (DBusWatchList *watch_list)
00223 {
00224
00225 _dbus_watch_list_set_functions (watch_list,
00226 NULL, NULL, NULL, NULL, NULL);
00227 _dbus_list_foreach (&watch_list->watches,
00228 (DBusForeachFunction) _dbus_watch_unref,
00229 NULL);
00230 _dbus_list_clear (&watch_list->watches);
00231
00232 dbus_free (watch_list);
00233 }
00234
00249 dbus_bool_t
00250 _dbus_watch_list_set_functions (DBusWatchList *watch_list,
00251 DBusAddWatchFunction add_function,
00252 DBusRemoveWatchFunction remove_function,
00253 DBusWatchToggledFunction toggled_function,
00254 void *data,
00255 DBusFreeFunction free_data_function)
00256 {
00257
00258 if (add_function != NULL)
00259 {
00260 DBusList *link;
00261
00262 link = _dbus_list_get_first_link (&watch_list->watches);
00263 while (link != NULL)
00264 {
00265 DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
00266 link);
00267
00268 _dbus_verbose ("Adding a watch on fd %d using newly-set add watch function\n",
00269 dbus_watch_get_fd (link->data));
00270
00271 if (!(* add_function) (link->data, data))
00272 {
00273
00274 DBusList *link2;
00275
00276 link2 = _dbus_list_get_first_link (&watch_list->watches);
00277 while (link2 != link)
00278 {
00279 DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
00280 link2);
00281
00282 _dbus_verbose ("Removing watch on fd %d using newly-set remove function because initial add failed\n",
00283 dbus_watch_get_fd (link2->data));
00284
00285 (* remove_function) (link2->data, data);
00286
00287 link2 = next;
00288 }
00289
00290 return FALSE;
00291 }
00292
00293 link = next;
00294 }
00295 }
00296
00297
00298
00299 if (watch_list->remove_watch_function != NULL)
00300 {
00301 _dbus_verbose ("Removing all pre-existing watches\n");
00302
00303 _dbus_list_foreach (&watch_list->watches,
00304 (DBusForeachFunction) watch_list->remove_watch_function,
00305 watch_list->watch_data);
00306 }
00307
00308 if (watch_list->watch_free_data_function != NULL)
00309 (* watch_list->watch_free_data_function) (watch_list->watch_data);
00310
00311 watch_list->add_watch_function = add_function;
00312 watch_list->remove_watch_function = remove_function;
00313 watch_list->watch_toggled_function = toggled_function;
00314 watch_list->watch_data = data;
00315 watch_list->watch_free_data_function = free_data_function;
00316
00317 return TRUE;
00318 }
00319
00328 dbus_bool_t
00329 _dbus_watch_list_add_watch (DBusWatchList *watch_list,
00330 DBusWatch *watch)
00331 {
00332 if (!_dbus_list_append (&watch_list->watches, watch))
00333 return FALSE;
00334
00335 _dbus_watch_ref (watch);
00336
00337 if (watch_list->add_watch_function != NULL)
00338 {
00339 _dbus_verbose ("Adding watch on fd %d\n",
00340 dbus_watch_get_fd (watch));
00341
00342 if (!(* watch_list->add_watch_function) (watch,
00343 watch_list->watch_data))
00344 {
00345 _dbus_list_remove_last (&watch_list->watches, watch);
00346 _dbus_watch_unref (watch);
00347 return FALSE;
00348 }
00349 }
00350
00351 return TRUE;
00352 }
00353
00361 void
00362 _dbus_watch_list_remove_watch (DBusWatchList *watch_list,
00363 DBusWatch *watch)
00364 {
00365 if (!_dbus_list_remove (&watch_list->watches, watch))
00366 _dbus_assert_not_reached ("Nonexistent watch was removed");
00367
00368 if (watch_list->remove_watch_function != NULL)
00369 {
00370 _dbus_verbose ("Removing watch on fd %d\n",
00371 dbus_watch_get_fd (watch));
00372
00373 (* watch_list->remove_watch_function) (watch,
00374 watch_list->watch_data);
00375 }
00376
00377 _dbus_watch_unref (watch);
00378 }
00379
00388 void
00389 _dbus_watch_list_toggle_watch (DBusWatchList *watch_list,
00390 DBusWatch *watch,
00391 dbus_bool_t enabled)
00392 {
00393 enabled = !!enabled;
00394
00395 if (enabled == watch->enabled)
00396 return;
00397
00398 watch->enabled = enabled;
00399
00400 if (watch_list->watch_toggled_function != NULL)
00401 {
00402 _dbus_verbose ("Toggling watch on fd %d to %d\n",
00403 dbus_watch_get_fd (watch), watch->enabled);
00404
00405 (* watch_list->watch_toggled_function) (watch,
00406 watch_list->watch_data);
00407 }
00408 }
00409
00422 void
00423 _dbus_watch_set_handler (DBusWatch *watch,
00424 DBusWatchHandler handler,
00425 void *data,
00426 DBusFreeFunction free_data_function)
00427 {
00428 if (watch->free_handler_data_function)
00429 (* watch->free_handler_data_function) (watch->handler_data);
00430
00431 watch->handler = handler;
00432 watch->handler_data = data;
00433 watch->free_handler_data_function = free_data_function;
00434 }
00435
00464 int
00465 dbus_watch_get_fd (DBusWatch *watch)
00466 {
00467 return watch->fd;
00468 }
00469
00483 unsigned int
00484 dbus_watch_get_flags (DBusWatch *watch)
00485 {
00486 _dbus_assert ((watch->flags & VALID_WATCH_FLAGS) == watch->flags);
00487
00488 return watch->flags;
00489 }
00490
00498 void*
00499 dbus_watch_get_data (DBusWatch *watch)
00500 {
00501 return watch->data;
00502 }
00503
00515 void
00516 dbus_watch_set_data (DBusWatch *watch,
00517 void *data,
00518 DBusFreeFunction free_data_function)
00519 {
00520 _dbus_verbose ("Setting watch fd %d data to data = %p function = %p from data = %p function = %p\n",
00521 dbus_watch_get_fd (watch),
00522 data, free_data_function, watch->data, watch->free_data_function);
00523
00524 if (watch->free_data_function != NULL)
00525 (* watch->free_data_function) (watch->data);
00526
00527 watch->data = data;
00528 watch->free_data_function = free_data_function;
00529 }
00530
00538 dbus_bool_t
00539 dbus_watch_get_enabled (DBusWatch *watch)
00540 {
00541 _dbus_assert (watch != NULL);
00542 return watch->enabled;
00543 }
00544
00545
00568 dbus_bool_t
00569 dbus_watch_handle (DBusWatch *watch,
00570 unsigned int flags)
00571 {
00572 #ifndef DBUS_DISABLE_CHECKS
00573 if (watch->fd < 0 || watch->flags == 0)
00574 {
00575 _dbus_warn ("%s: Watch is invalid, it should have been removed\n",
00576 _DBUS_FUNCTION_NAME);
00577 return TRUE;
00578 }
00579 #endif
00580
00581 _dbus_return_val_if_fail (watch->fd >= 0 , TRUE);
00582
00583 _dbus_watch_sanitize_condition (watch, &flags);
00584
00585 if (flags == 0)
00586 {
00587 _dbus_verbose ("After sanitization, watch flags on fd %d were 0\n",
00588 watch->fd);
00589 return TRUE;
00590 }
00591 else
00592 return (* watch->handler) (watch, flags,
00593 watch->handler_data);
00594 }
00595
00596