2003-08-14 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-pending-call.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-pending-call.c Object representing a call in progress.
3  *
4  * Copyright (C) 2002, 2003 Red Hat Inc.
5  *
6  * Licensed under the Academic Free License version 1.2
7  *
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.
12  *
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.
17  *
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
21  *
22  */
23
24 #include "dbus-internals.h"
25 #include "dbus-message-pending.h"
26 #include "dbus-list.h"
27 #include "dbus-threads.h"
28 #include "dbus-test.h"
29 #include "dbus-connection-internal.h"
30
31 /**
32  * @defgroup DBusPendingCallInternals DBusPendingCall implementation details
33  * @ingroup DBusInternals
34  * @brief DBusPendingCall private implementation details.
35  *
36  * The guts of DBusPendingCall and its methods.
37  *
38  * @{
39  */
40
41 /**
42  * @brief Internals of DBusPendingCall
43  *
44  * Object representing a reply message that we're waiting for.
45  */
46 struct DBusPendingCall
47 {
48   DBusAtomic refcount;                            /**< reference count */
49
50   DBusPendingCallNotifyFunction function;         /**< Notifier when reply arrives. */
51   void                     *user_data;            /**< user data for function */
52   DBusFreeFunction          free_user_data;       /**< free the user data */
53
54   DBusConnection *connection;                     /**< Connections we're associated with */
55   DBusMessage *reply;                             /**< Reply (after we've received it) */
56   DBusTimeout *timeout;                           /**< Timeout */
57
58   DBusList *timeout_link;                         /**< Preallocated timeout response */
59   
60   dbus_uint32_t reply_serial;                     /**< Expected serial of reply */
61
62   unsigned int completed : 1;                     /**< TRUE if completed */
63   unsigned int timeout_added : 1;                 /**< Have added the timeout */
64 };
65
66 /**
67  * Creates a new pending reply object.
68  *
69  * @param connection connection where reply will arrive
70  * @param reply_serial reply serial of the expected reply
71  * @returns a new #DBusPendingCall or #NULL if no memory.
72  */
73 DBusPendingCall*
74 _dbus_pending_call_new (DBusConnection *connection,
75                        dbus_uint32_t    reply_serial)
76 {
77   DBusPendingCall *pending;
78
79   pending = dbus_new (DBusPendingCall, 1);
80   
81   if (pending == NULL)
82     return NULL;
83
84   pending->refcount.value = 1;
85   pending->connection = connection;
86   pending->reply_serial = reply_serial;
87
88   return pending;
89 }
90
91 /** @} */
92
93 /**
94  * @defgroup DBusPendingCall DBusPendingCall
95  * @ingroup  DBus
96  * @brief Pending reply to a method call message
97  *
98  * A DBusPendingCall is an object representing an
99  * expected reply. A #DBusPendingCall can be created
100  * when you send a message that should have a reply.
101  *
102  * @{
103  */
104
105 /**
106  * @typedef DBusPendingCall
107  *
108  * Opaque data type representing a message pending.
109  */
110
111 /**
112  * Increments the reference count on a pending call.
113  *
114  * @param pending the pending call object
115  */
116 void
117 dbus_pending_call_ref (DBusPendingCall *pending)
118 {
119   _dbus_return_if_fail (pending != NULL);
120
121   _dbus_atomic_inc (&pending->refcount);
122 }
123
124 /**
125  * Decrements the reference count on a pending call,
126  * freeing it if the count reaches 0.
127  *
128  * @param pending the pending call object
129  */
130 void
131 dbus_pending_call_unref (DBusPendingCall *pending)
132 {
133   dbus_bool_t last_unref;
134
135   _dbus_return_if_fail (pending != NULL);
136
137   last_unref = (_dbus_atomic_dec (&pending->refcount) == 1);
138
139   if (last_unref)
140     {
141       if (pending->free_user_data)
142         (* pending->free_user_data) (pending->user_data);
143
144
145       if (pending->connection != NULL)
146         {
147           _dbus_connection_pending_destroyed_locked (connection, pending);
148           pending->connection = NULL;
149         }
150
151       if (pending->reply)
152         {
153           dbus_message_unref (pending->reply);
154           pending->reply = NULL;
155         }
156       
157       dbus_free (pending);
158     }
159 }
160
161 /**
162  * Sets a notification function to be called when the reply is
163  * received or the pending call times out.
164  *
165  * @param pending the pending call
166  * @param function notifier function
167  * @param user_data data to pass to notifier function
168  * @param free_user_data function to free the user data
169  * 
170  */
171 void
172 dbus_pending_call_set_notify (DBusPendingCall              *pending,
173                               DBusPendingCallNotifyFunction function,
174                               void                         *user_data,
175                               DBusFreeFunction              free_user_data)
176 {
177   DBusFreeFunction old_free_func;
178   void *old_user_data;
179
180   _dbus_return_if_fail (pending != NULL);
181
182   _DBUS_LOCK (pending_call);
183   old_free_func = pending->free_user_data;
184   old_user_data = pending->user_data;
185
186   pending->user_data = user_data;
187   pending->free_user_data = free_user_data;
188   pending->function = function;
189   _DBUS_UNLOCK (pending_call);
190
191   if (old_free_func)
192     (* old_free_func) (old_user_data);
193 }
194
195 /** @} */
196
197 #ifdef DBUS_BUILD_TESTS
198 static DBusPendingResult
199 test_pending (DBusPendingCall *pending,
200               DBusConnection     *connection,
201               DBusMessage        *message,
202               void               *user_data)
203 {
204   return DBUS_PENDING_RESULT_NOT_YET_HANDLED;
205 }
206
207 static void
208 free_test_data (void *data)
209 {
210   /* does nothing */
211 }
212
213 /**
214  * @ingroup DBusPendingCallInternals
215  * Unit test for DBusPendingCall.
216  *
217  * @returns #TRUE on success.
218  */
219 dbus_bool_t
220 _dbus_pending_call_test (const char *test_data_dir)
221 {  
222
223   return TRUE;
224 }
225 #endif /* DBUS_BUILD_TESTS */