Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

dbus-pending-call.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-pending-call.c Object representing a call in progress.
00003  *
00004  * Copyright (C) 2002, 2003 Red Hat Inc.
00005  *
00006  * Licensed under the Academic Free License version 1.2
00007  *
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 (&notify_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 (&notify_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 (&notify_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       /* If we get here, we should be already detached
00168        * from the connection, or never attached.
00169        */
00170       _dbus_assert (pending->connection == NULL);
00171       _dbus_assert (!pending->timeout_added);  
00172 
00173       /* this assumes we aren't holding connection lock... */
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 (&notify_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   /* could invoke application code! */
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   /* message may be NULL if no reply */
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 /* DBUS_BUILD_TESTS */

Generated on Tue Feb 10 18:14:06 2004 for D-BUS by doxygen 1.3.5