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