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_assert (timeout_milliseconds >= 0 || timeout_milliseconds == -1);
00060
00061 if (timeout_milliseconds == -1)
00062 timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE;
00063
00064
00065
00066
00067
00068
00069 if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6)
00070 timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6;
00071
00072 if (!dbus_pending_call_allocate_data_slot (¬ify_user_data_slot))
00073 return NULL;
00074
00075 pending = dbus_new0 (DBusPendingCall, 1);
00076
00077 if (pending == NULL)
00078 {
00079 dbus_pending_call_free_data_slot (¬ify_user_data_slot);
00080 return NULL;
00081 }
00082
00083 timeout = _dbus_timeout_new (timeout_milliseconds,
00084 timeout_handler,
00085 pending, NULL);
00086
00087 if (timeout == NULL)
00088 {
00089 dbus_pending_call_free_data_slot (¬ify_user_data_slot);
00090 dbus_free (pending);
00091 return NULL;
00092 }
00093
00094 pending->refcount.value = 1;
00095 pending->connection = connection;
00096 pending->timeout = timeout;
00097
00098 _dbus_data_slot_list_init (&pending->slot_list);
00099
00100 return pending;
00101 }
00102
00110 void
00111 _dbus_pending_call_notify (DBusPendingCall *pending)
00112 {
00113 _dbus_assert (!pending->completed);
00114
00115 pending->completed = TRUE;
00116
00117 if (pending->function)
00118 {
00119 void *user_data;
00120 user_data = dbus_pending_call_get_data (pending,
00121 notify_user_data_slot);
00122
00123 (* pending->function) (pending, user_data);
00124 }
00125 }
00126
00153 DBusPendingCall *
00154 dbus_pending_call_ref (DBusPendingCall *pending)
00155 {
00156 _dbus_return_val_if_fail (pending != NULL, NULL);
00157
00158 _dbus_atomic_inc (&pending->refcount);
00159
00160 return pending;
00161 }
00162
00169 void
00170 dbus_pending_call_unref (DBusPendingCall *pending)
00171 {
00172 dbus_bool_t last_unref;
00173
00174 _dbus_return_if_fail (pending != NULL);
00175
00176 last_unref = (_dbus_atomic_dec (&pending->refcount) == 1);
00177
00178 if (last_unref)
00179 {
00180
00181
00182
00183 _dbus_assert (pending->connection == NULL);
00184 _dbus_assert (!pending->timeout_added);
00185
00186
00187 _dbus_data_slot_list_free (&pending->slot_list);
00188
00189 if (pending->timeout != NULL)
00190 _dbus_timeout_unref (pending->timeout);
00191
00192 if (pending->timeout_link)
00193 {
00194 dbus_message_unref ((DBusMessage *)pending->timeout_link->data);
00195 _dbus_list_free_link (pending->timeout_link);
00196 pending->timeout_link = NULL;
00197 }
00198
00199 if (pending->reply)
00200 {
00201 dbus_message_unref (pending->reply);
00202 pending->reply = NULL;
00203 }
00204
00205 dbus_free (pending);
00206
00207 dbus_pending_call_free_data_slot (¬ify_user_data_slot);
00208 }
00209 }
00210
00221 dbus_bool_t
00222 dbus_pending_call_set_notify (DBusPendingCall *pending,
00223 DBusPendingCallNotifyFunction function,
00224 void *user_data,
00225 DBusFreeFunction free_user_data)
00226 {
00227 _dbus_return_val_if_fail (pending != NULL, FALSE);
00228
00229
00230 if (!dbus_pending_call_set_data (pending, notify_user_data_slot,
00231 user_data, free_user_data))
00232 return FALSE;
00233
00234 pending->function = function;
00235
00236 return TRUE;
00237 }
00238
00248 void
00249 dbus_pending_call_cancel (DBusPendingCall *pending)
00250 {
00251 if (pending->connection)
00252 _dbus_connection_remove_pending_call (pending->connection,
00253 pending);
00254 }
00255
00264 dbus_bool_t
00265 dbus_pending_call_get_completed (DBusPendingCall *pending)
00266 {
00267 return pending->completed;
00268 }
00269
00279 DBusMessage*
00280 dbus_pending_call_steal_reply (DBusPendingCall *pending)
00281 {
00282 DBusMessage *message;
00283
00284 _dbus_return_val_if_fail (pending->completed, NULL);
00285 _dbus_return_val_if_fail (pending->reply != NULL, NULL);
00286
00287 message = pending->reply;
00288 pending->reply = NULL;
00289
00290 return message;
00291 }
00292
00305 DBusMessage*
00306 dbus_pending_call_get_reply (DBusPendingCall *pending)
00307 {
00308 return pending->reply;
00309 }
00310
00325 void
00326 dbus_pending_call_block (DBusPendingCall *pending)
00327 {
00328 _dbus_connection_block_pending_call (pending);
00329 }
00330
00331 static DBusDataSlotAllocator slot_allocator;
00332 _DBUS_DEFINE_GLOBAL_LOCK (pending_call_slots);
00333
00348 dbus_bool_t
00349 dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p)
00350 {
00351 return _dbus_data_slot_allocator_alloc (&slot_allocator,
00352 _DBUS_LOCK_NAME (pending_call_slots),
00353 slot_p);
00354 }
00355
00367 void
00368 dbus_pending_call_free_data_slot (dbus_int32_t *slot_p)
00369 {
00370 _dbus_return_if_fail (*slot_p >= 0);
00371
00372 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
00373 }
00374
00388 dbus_bool_t
00389 dbus_pending_call_set_data (DBusPendingCall *pending,
00390 dbus_int32_t slot,
00391 void *data,
00392 DBusFreeFunction free_data_func)
00393 {
00394 DBusFreeFunction old_free_func;
00395 void *old_data;
00396 dbus_bool_t retval;
00397
00398 _dbus_return_val_if_fail (pending != NULL, FALSE);
00399 _dbus_return_val_if_fail (slot >= 0, FALSE);
00400
00401 retval = _dbus_data_slot_list_set (&slot_allocator,
00402 &pending->slot_list,
00403 slot, data, free_data_func,
00404 &old_free_func, &old_data);
00405
00406 if (retval)
00407 {
00408 if (old_free_func)
00409 (* old_free_func) (old_data);
00410 }
00411
00412 return retval;
00413 }
00414
00423 void*
00424 dbus_pending_call_get_data (DBusPendingCall *pending,
00425 dbus_int32_t slot)
00426 {
00427 void *res;
00428
00429 _dbus_return_val_if_fail (pending != NULL, NULL);
00430
00431 res = _dbus_data_slot_list_get (&slot_allocator,
00432 &pending->slot_list,
00433 slot);
00434
00435 return res;
00436 }
00437
00440 #ifdef DBUS_BUILD_TESTS
00441
00448 dbus_bool_t
00449 _dbus_pending_call_test (const char *test_data_dir)
00450 {
00451
00452 return TRUE;
00453 }
00454 #endif