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
00142 void
00143 dbus_pending_call_ref (DBusPendingCall *pending)
00144 {
00145 _dbus_return_if_fail (pending != NULL);
00146
00147 _dbus_atomic_inc (&pending->refcount);
00148 }
00149
00156 void
00157 dbus_pending_call_unref (DBusPendingCall *pending)
00158 {
00159 dbus_bool_t last_unref;
00160
00161 _dbus_return_if_fail (pending != NULL);
00162
00163 last_unref = (_dbus_atomic_dec (&pending->refcount) == 1);
00164
00165 if (last_unref)
00166 {
00167
00168
00169
00170 _dbus_assert (pending->connection == NULL);
00171 _dbus_assert (!pending->timeout_added);
00172
00173
00174 _dbus_data_slot_list_free (&pending->slot_list);
00175
00176 if (pending->timeout != NULL)
00177 _dbus_timeout_unref (pending->timeout);
00178
00179 if (pending->timeout_link)
00180 {
00181 dbus_message_unref ((DBusMessage *)pending->timeout_link->data);
00182 _dbus_list_free_link (pending->timeout_link);
00183 pending->timeout_link = NULL;
00184 }
00185
00186 if (pending->reply)
00187 {
00188 dbus_message_unref (pending->reply);
00189 pending->reply = NULL;
00190 }
00191
00192 dbus_free (pending);
00193
00194 dbus_pending_call_free_data_slot (¬ify_user_data_slot);
00195 }
00196 }
00197
00208 dbus_bool_t
00209 dbus_pending_call_set_notify (DBusPendingCall *pending,
00210 DBusPendingCallNotifyFunction function,
00211 void *user_data,
00212 DBusFreeFunction free_user_data)
00213 {
00214 _dbus_return_val_if_fail (pending != NULL, FALSE);
00215
00216
00217 if (!dbus_pending_call_set_data (pending, notify_user_data_slot,
00218 user_data, free_user_data))
00219 return FALSE;
00220
00221 pending->function = function;
00222
00223 return TRUE;
00224 }
00225
00235 void
00236 dbus_pending_call_cancel (DBusPendingCall *pending)
00237 {
00238 if (pending->connection)
00239 _dbus_connection_remove_pending_call (pending->connection,
00240 pending);
00241 }
00242
00251 dbus_bool_t
00252 dbus_pending_call_get_completed (DBusPendingCall *pending)
00253 {
00254 return pending->completed;
00255 }
00256
00269 DBusMessage*
00270 dbus_pending_call_get_reply (DBusPendingCall *pending)
00271 {
00272 return pending->reply;
00273 }
00274
00289 void
00290 dbus_pending_call_block (DBusPendingCall *pending)
00291 {
00292 DBusMessage *message;
00293
00294 if (dbus_pending_call_get_completed (pending))
00295 return;
00296
00297
00298 message = _dbus_connection_block_for_reply (pending->connection,
00299 pending->reply_serial,
00300 dbus_timeout_get_interval (pending->timeout));
00301
00302 _dbus_connection_lock (pending->connection);
00303 _dbus_pending_call_complete_and_unlock (pending, message);
00304 if (message)
00305 dbus_message_unref (message);
00306 }
00307
00308 static DBusDataSlotAllocator slot_allocator;
00309 _DBUS_DEFINE_GLOBAL_LOCK (pending_call_slots);
00310
00325 dbus_bool_t
00326 dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p)
00327 {
00328 return _dbus_data_slot_allocator_alloc (&slot_allocator,
00329 _DBUS_LOCK_NAME (pending_call_slots),
00330 slot_p);
00331 }
00332
00344 void
00345 dbus_pending_call_free_data_slot (dbus_int32_t *slot_p)
00346 {
00347 _dbus_return_if_fail (*slot_p >= 0);
00348
00349 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
00350 }
00351
00365 dbus_bool_t
00366 dbus_pending_call_set_data (DBusPendingCall *pending,
00367 dbus_int32_t slot,
00368 void *data,
00369 DBusFreeFunction free_data_func)
00370 {
00371 DBusFreeFunction old_free_func;
00372 void *old_data;
00373 dbus_bool_t retval;
00374
00375 _dbus_return_val_if_fail (pending != NULL, FALSE);
00376 _dbus_return_val_if_fail (slot >= 0, FALSE);
00377
00378 retval = _dbus_data_slot_list_set (&slot_allocator,
00379 &pending->slot_list,
00380 slot, data, free_data_func,
00381 &old_free_func, &old_data);
00382
00383 if (retval)
00384 {
00385 if (old_free_func)
00386 (* old_free_func) (old_data);
00387 }
00388
00389 return retval;
00390 }
00391
00400 void*
00401 dbus_pending_call_get_data (DBusPendingCall *pending,
00402 dbus_int32_t slot)
00403 {
00404 void *res;
00405
00406 _dbus_return_val_if_fail (pending != NULL, NULL);
00407
00408 res = _dbus_data_slot_list_get (&slot_allocator,
00409 &pending->slot_list,
00410 slot);
00411
00412 return res;
00413 }
00414
00417 #ifdef DBUS_BUILD_TESTS
00418
00425 dbus_bool_t
00426 _dbus_pending_call_test (const char *test_data_dir)
00427 {
00428
00429 return TRUE;
00430 }
00431 #endif