1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-pending-call.c Object representing a call in progress.
4 * Copyright (C) 2002, 2003 Red Hat Inc.
6 * Licensed under the Academic Free License version 1.2
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "dbus-internals.h"
25 #include "dbus-connection-internal.h"
26 #include "dbus-pending-call.h"
27 #include "dbus-list.h"
28 #include "dbus-threads.h"
29 #include "dbus-test.h"
32 * @defgroup DBusPendingCallInternals DBusPendingCall implementation details
33 * @ingroup DBusInternals
34 * @brief DBusPendingCall private implementation details.
36 * The guts of DBusPendingCall and its methods.
42 * Creates a new pending reply object.
44 * @param connection connection where reply will arrive
45 * @param timeout_milliseconds length of timeout, -1 for default
46 * @param timeout_handler timeout handler, takes pending call as data
47 * @returns a new #DBusPendingCall or #NULL if no memory.
50 _dbus_pending_call_new (DBusConnection *connection,
51 int timeout_milliseconds,
52 DBusTimeoutHandler timeout_handler)
54 DBusPendingCall *pending;
57 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
59 if (timeout_milliseconds == -1)
60 timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE;
62 pending = dbus_new (DBusPendingCall, 1);
67 timeout = _dbus_timeout_new (timeout_milliseconds,
77 pending->refcount.value = 1;
78 pending->connection = connection;
79 pending->timeout = timeout;
85 * Calls notifier function for the pending call
86 * and sets the call to completed.
88 * @param pending the pending call
92 _dbus_pending_call_notify (DBusPendingCall *pending)
94 pending->completed = TRUE;
96 if (pending->function)
97 (* pending->function) (pending, pending->user_data);
103 * @defgroup DBusPendingCall DBusPendingCall
105 * @brief Pending reply to a method call message
107 * A DBusPendingCall is an object representing an
108 * expected reply. A #DBusPendingCall can be created
109 * when you send a message that should have a reply.
115 * @typedef DBusPendingCall
117 * Opaque data type representing a message pending.
121 * Increments the reference count on a pending call.
123 * @param pending the pending call object
126 dbus_pending_call_ref (DBusPendingCall *pending)
128 _dbus_return_if_fail (pending != NULL);
130 _dbus_atomic_inc (&pending->refcount);
134 * Decrements the reference count on a pending call,
135 * freeing it if the count reaches 0.
137 * @param pending the pending call object
140 dbus_pending_call_unref (DBusPendingCall *pending)
142 dbus_bool_t last_unref;
144 _dbus_return_if_fail (pending != NULL);
146 last_unref = (_dbus_atomic_dec (&pending->refcount) == 1);
150 /* If we get here, we should be already detached
151 * from the connection, or never attached.
153 _dbus_assert (pending->connection == NULL);
154 _dbus_assert (!pending->timeout_added);
156 /* this assumes we aren't holding connection lock... */
157 if (pending->free_user_data)
158 (* pending->free_user_data) (pending->user_data);
160 if (pending->timeout != NULL)
161 _dbus_timeout_unref (pending->timeout);
163 if (pending->timeout_link)
165 dbus_message_unref ((DBusMessage *)pending->timeout_link->data);
166 _dbus_list_free_link (pending->timeout_link);
167 pending->timeout_link = NULL;
172 dbus_message_unref (pending->reply);
173 pending->reply = NULL;
181 * Sets a notification function to be called when the reply is
182 * received or the pending call times out.
184 * @param pending the pending call
185 * @param function notifier function
186 * @param user_data data to pass to notifier function
187 * @param free_user_data function to free the user data
191 dbus_pending_call_set_notify (DBusPendingCall *pending,
192 DBusPendingCallNotifyFunction function,
194 DBusFreeFunction free_user_data)
196 DBusFreeFunction old_free_func;
199 _dbus_return_if_fail (pending != NULL);
201 old_free_func = pending->free_user_data;
202 old_user_data = pending->user_data;
204 pending->user_data = user_data;
205 pending->free_user_data = free_user_data;
206 pending->function = function;
209 (* old_free_func) (old_user_data);
213 * Cancels the pending call, such that any reply
214 * or error received will just be ignored.
215 * Drops at least one reference to the #DBusPendingCall
216 * so will free the call if nobody else is holding
219 * @param pending the pending call
222 dbus_pending_call_cancel (DBusPendingCall *pending)
224 if (pending->connection)
225 _dbus_connection_remove_pending_call (pending->connection,
230 * Checks whether the pending call has received a reply
233 * @param pending the pending call
234 * @returns #TRUE if a reply has been received
237 dbus_pending_call_get_completed (DBusPendingCall *pending)
239 return pending->completed;
243 * Gets the reply, or returns #NULL if none has been received yet. The
244 * reference count is not incremented on the returned message, so you
245 * have to keep a reference count on the pending call (or add one
248 * @param pending the pending call
249 * @returns the reply message or #NULL.
252 dbus_pending_call_get_reply (DBusPendingCall *pending)
254 return pending->reply;
258 * Block until the pending call is completed. The blocking is as with
259 * dbus_connection_send_with_reply_and_block(); it does not enter the
260 * main loop or process other messages, it simply waits for the reply
263 * @todo when you start blocking, the timeout is reset, but it should
264 * really only use time remaining since the pending call was created.
266 * @param pending the pending call
269 dbus_pending_call_block (DBusPendingCall *pending)
271 DBusMessage *message;
273 message = _dbus_connection_block_for_reply (pending->connection,
274 pending->reply_serial,
275 dbus_timeout_get_interval (pending->timeout));
277 _dbus_connection_lock (pending->connection);
278 _dbus_pending_call_complete_and_unlock (pending, message);
279 dbus_message_unref (message);
284 #ifdef DBUS_BUILD_TESTS
287 * @ingroup DBusPendingCallInternals
288 * Unit test for DBusPendingCall.
290 * @returns #TRUE on success.
293 _dbus_pending_call_test (const char *test_data_dir)
298 #endif /* DBUS_BUILD_TESTS */