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-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 (¬ify_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 (¬ify_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 (¬ify_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
00171
00172
00173 _dbus_assert (pending->connection == NULL);
00174 _dbus_assert (!pending->timeout_added);
00175
00176
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 (¬ify_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
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
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