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

dbus-pending-call.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */ 00002 /* dbus-pending-call.c Object representing a call in progress. 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-connection-internal.h" 00026 #include "dbus-pending-call.h" 00027 #include "dbus-list.h" 00028 #include "dbus-threads.h" 00029 #include "dbus-test.h" 00030 00041 static dbus_int32_t notify_user_data_slot = -1; 00042 00051 DBusPendingCall* 00052 _dbus_pending_call_new (DBusConnection *connection, 00053 int timeout_milliseconds, 00054 DBusTimeoutHandler timeout_handler) 00055 { 00056 DBusPendingCall *pending; 00057 DBusTimeout *timeout; 00058 00059 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 00060 00061 if (timeout_milliseconds == -1) 00062 timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE; 00063 00064 if (!dbus_pending_call_allocate_data_slot (&notify_user_data_slot)) 00065 return NULL; 00066 00067 pending = dbus_new0 (DBusPendingCall, 1); 00068 00069 if (pending == NULL) 00070 { 00071 dbus_pending_call_free_data_slot (&notify_user_data_slot); 00072 return NULL; 00073 } 00074 00075 timeout = _dbus_timeout_new (timeout_milliseconds, 00076 timeout_handler, 00077 pending, NULL); 00078 00079 if (timeout == NULL) 00080 { 00081 dbus_pending_call_free_data_slot (&notify_user_data_slot); 00082 dbus_free (pending); 00083 return NULL; 00084 } 00085 00086 pending->refcount.value = 1; 00087 pending->connection = connection; 00088 pending->timeout = timeout; 00089 00090 _dbus_data_slot_list_init (&pending->slot_list); 00091 00092 return pending; 00093 } 00094 00102 void 00103 _dbus_pending_call_notify (DBusPendingCall *pending) 00104 { 00105 pending->completed = TRUE; 00106 00107 if (pending->function) 00108 { 00109 void *user_data; 00110 user_data = dbus_pending_call_get_data (pending, 00111 notify_user_data_slot); 00112 00113 (* pending->function) (pending, user_data); 00114 } 00115 } 00116 00143 DBusPendingCall * 00144 dbus_pending_call_ref (DBusPendingCall *pending) 00145 { 00146 _dbus_return_val_if_fail (pending != NULL, NULL); 00147 00148 _dbus_atomic_inc (&pending->refcount); 00149 00150 return pending; 00151 } 00152 00159 void 00160 dbus_pending_call_unref (DBusPendingCall *pending) 00161 { 00162 dbus_bool_t last_unref; 00163 00164 _dbus_return_if_fail (pending != NULL); 00165 00166 last_unref = (_dbus_atomic_dec (&pending->refcount) == 1); 00167 00168 if (last_unref) 00169 { 00170 /* If we get here, we should be already detached 00171 * from the connection, or never attached. 00172 */ 00173 _dbus_assert (pending->connection == NULL); 00174 _dbus_assert (!pending->timeout_added); 00175 00176 /* this assumes we aren't holding connection lock... */ 00177 _dbus_data_slot_list_free (&pending->slot_list); 00178 00179 if (pending->timeout != NULL) 00180 _dbus_timeout_unref (pending->timeout); 00181 00182 if (pending->timeout_link) 00183 { 00184 dbus_message_unref ((DBusMessage *)pending->timeout_link->data); 00185 _dbus_list_free_link (pending->timeout_link); 00186 pending->timeout_link = NULL; 00187 } 00188 00189 if (pending->reply) 00190 { 00191 dbus_message_unref (pending->reply); 00192 pending->reply = NULL; 00193 } 00194 00195 dbus_free (pending); 00196 00197 dbus_pending_call_free_data_slot (&notify_user_data_slot); 00198 } 00199 } 00200 00211 dbus_bool_t 00212 dbus_pending_call_set_notify (DBusPendingCall *pending, 00213 DBusPendingCallNotifyFunction function, 00214 void *user_data, 00215 DBusFreeFunction free_user_data) 00216 { 00217 _dbus_return_val_if_fail (pending != NULL, FALSE); 00218 00219 /* could invoke application code! */ 00220 if (!dbus_pending_call_set_data (pending, notify_user_data_slot, 00221 user_data, free_user_data)) 00222 return FALSE; 00223 00224 pending->function = function; 00225 00226 return TRUE; 00227 } 00228 00238 void 00239 dbus_pending_call_cancel (DBusPendingCall *pending) 00240 { 00241 if (pending->connection) 00242 _dbus_connection_remove_pending_call (pending->connection, 00243 pending); 00244 } 00245 00254 dbus_bool_t 00255 dbus_pending_call_get_completed (DBusPendingCall *pending) 00256 { 00257 return pending->completed; 00258 } 00259 00272 DBusMessage* 00273 dbus_pending_call_get_reply (DBusPendingCall *pending) 00274 { 00275 return pending->reply; 00276 } 00277 00292 void 00293 dbus_pending_call_block (DBusPendingCall *pending) 00294 { 00295 DBusMessage *message; 00296 00297 if (dbus_pending_call_get_completed (pending)) 00298 return; 00299 00300 /* message may be NULL if no reply */ 00301 message = _dbus_connection_block_for_reply (pending->connection, 00302 pending->reply_serial, 00303 dbus_timeout_get_interval (pending->timeout)); 00304 00305 _dbus_connection_lock (pending->connection); 00306 _dbus_pending_call_complete_and_unlock (pending, message); 00307 if (message) 00308 dbus_message_unref (message); 00309 } 00310 00311 static DBusDataSlotAllocator slot_allocator; 00312 _DBUS_DEFINE_GLOBAL_LOCK (pending_call_slots); 00313 00328 dbus_bool_t 00329 dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p) 00330 { 00331 return _dbus_data_slot_allocator_alloc (&slot_allocator, 00332 _DBUS_LOCK_NAME (pending_call_slots), 00333 slot_p); 00334 } 00335 00347 void 00348 dbus_pending_call_free_data_slot (dbus_int32_t *slot_p) 00349 { 00350 _dbus_return_if_fail (*slot_p >= 0); 00351 00352 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 00353 } 00354 00368 dbus_bool_t 00369 dbus_pending_call_set_data (DBusPendingCall *pending, 00370 dbus_int32_t slot, 00371 void *data, 00372 DBusFreeFunction free_data_func) 00373 { 00374 DBusFreeFunction old_free_func; 00375 void *old_data; 00376 dbus_bool_t retval; 00377 00378 _dbus_return_val_if_fail (pending != NULL, FALSE); 00379 _dbus_return_val_if_fail (slot >= 0, FALSE); 00380 00381 retval = _dbus_data_slot_list_set (&slot_allocator, 00382 &pending->slot_list, 00383 slot, data, free_data_func, 00384 &old_free_func, &old_data); 00385 00386 if (retval) 00387 { 00388 if (old_free_func) 00389 (* old_free_func) (old_data); 00390 } 00391 00392 return retval; 00393 } 00394 00403 void* 00404 dbus_pending_call_get_data (DBusPendingCall *pending, 00405 dbus_int32_t slot) 00406 { 00407 void *res; 00408 00409 _dbus_return_val_if_fail (pending != NULL, NULL); 00410 00411 res = _dbus_data_slot_list_get (&slot_allocator, 00412 &pending->slot_list, 00413 slot); 00414 00415 return res; 00416 } 00417 00420 #ifdef DBUS_BUILD_TESTS 00421 00428 dbus_bool_t 00429 _dbus_pending_call_test (const char *test_data_dir) 00430 { 00431 00432 return TRUE; 00433 } 00434 #endif /* DBUS_BUILD_TESTS */

Generated on Tue Oct 12 02:07:53 2004 for D-BUS by doxygen 1.3.7