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
00307 void
00308 dbus_pending_call_block (DBusPendingCall *pending)
00309 {
00310 _dbus_connection_block_pending_call (pending);
00311 }
00312
00313 static DBusDataSlotAllocator slot_allocator;
00314 _DBUS_DEFINE_GLOBAL_LOCK (pending_call_slots);
00315
00330 dbus_bool_t
00331 dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p)
00332 {
00333 return _dbus_data_slot_allocator_alloc (&slot_allocator,
00334 _DBUS_LOCK_NAME (pending_call_slots),
00335 slot_p);
00336 }
00337
00349 void
00350 dbus_pending_call_free_data_slot (dbus_int32_t *slot_p)
00351 {
00352 _dbus_return_if_fail (*slot_p >= 0);
00353
00354 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
00355 }
00356
00370 dbus_bool_t
00371 dbus_pending_call_set_data (DBusPendingCall *pending,
00372 dbus_int32_t slot,
00373 void *data,
00374 DBusFreeFunction free_data_func)
00375 {
00376 DBusFreeFunction old_free_func;
00377 void *old_data;
00378 dbus_bool_t retval;
00379
00380 _dbus_return_val_if_fail (pending != NULL, FALSE);
00381 _dbus_return_val_if_fail (slot >= 0, FALSE);
00382
00383 retval = _dbus_data_slot_list_set (&slot_allocator,
00384 &pending->slot_list,
00385 slot, data, free_data_func,
00386 &old_free_func, &old_data);
00387
00388 if (retval)
00389 {
00390 if (old_free_func)
00391 (* old_free_func) (old_data);
00392 }
00393
00394 return retval;
00395 }
00396
00405 void*
00406 dbus_pending_call_get_data (DBusPendingCall *pending,
00407 dbus_int32_t slot)
00408 {
00409 void *res;
00410
00411 _dbus_return_val_if_fail (pending != NULL, NULL);
00412
00413 res = _dbus_data_slot_list_get (&slot_allocator,
00414 &pending->slot_list,
00415 slot);
00416
00417 return res;
00418 }
00419
00422 #ifdef DBUS_BUILD_TESTS
00423
00430 dbus_bool_t
00431 _dbus_pending_call_test (const char *test_data_dir)
00432 {
00433
00434 return TRUE;
00435 }
00436 #endif