Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

dbus-watch.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */ 00002 /* dbus-watch.c DBusWatch implementation 00003 * 00004 * Copyright (C) 2002, 2003 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-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); /* call free_data_function */ 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 /* free watch_data and removes watches as a side effect */ 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 /* Add watches with the new watch function, failing on OOM */ 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 /* remove it all again and return FALSE */ 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 /* Remove all current watches from previous watch handlers */ 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 /* fails if watch was removed */, 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

Generated on Mon Jun 27 07:48:23 2005 for D-BUS by doxygen 1.3.7