Main Page | Modules | Namespace List | Class Hierarchy | Data Structures | Directories | File List | Namespace Members | 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 2.1
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_assert (timeout_milliseconds >= 0 || timeout_milliseconds == -1);
00060   
00061   if (timeout_milliseconds == -1)
00062     timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE;
00063 
00064   /* it would probably seem logical to pass in _DBUS_INT_MAX for
00065    * infinite timeout, but then math in
00066    * _dbus_connection_block_for_reply would get all overflow-prone, so
00067    * smack that down.
00068    */
00069   if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6)
00070     timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6;
00071   
00072   if (!dbus_pending_call_allocate_data_slot (&notify_user_data_slot))
00073     return NULL;
00074   
00075   pending = dbus_new0 (DBusPendingCall, 1);
00076   
00077   if (pending == NULL)
00078     {
00079       dbus_pending_call_free_data_slot (&notify_user_data_slot);
00080       return NULL;
00081     }
00082 
00083   timeout = _dbus_timeout_new (timeout_milliseconds,
00084                                timeout_handler,
00085                                pending, NULL);  
00086 
00087   if (timeout == NULL)
00088     {
00089       dbus_pending_call_free_data_slot (&notify_user_data_slot);
00090       dbus_free (pending);
00091       return NULL;
00092     }
00093   
00094   pending->refcount.value = 1;
00095   pending->connection = connection;
00096   pending->timeout = timeout;
00097 
00098   _dbus_data_slot_list_init (&pending->slot_list);
00099   
00100   return pending;
00101 }
00102 
00110 void
00111 _dbus_pending_call_notify (DBusPendingCall *pending)
00112 {
00113   _dbus_assert (!pending->completed);
00114   
00115   pending->completed = TRUE;
00116 
00117   if (pending->function)
00118     {
00119       void *user_data;
00120       user_data = dbus_pending_call_get_data (pending,
00121                                               notify_user_data_slot);
00122       
00123       (* pending->function) (pending, user_data);
00124     }
00125 }
00126 
00153 DBusPendingCall *
00154 dbus_pending_call_ref (DBusPendingCall *pending)
00155 {
00156   _dbus_return_val_if_fail (pending != NULL, NULL);
00157 
00158   _dbus_atomic_inc (&pending->refcount);
00159 
00160   return pending;
00161 }
00162 
00169 void
00170 dbus_pending_call_unref (DBusPendingCall *pending)
00171 {
00172   dbus_bool_t last_unref;
00173 
00174   _dbus_return_if_fail (pending != NULL);
00175 
00176   last_unref = (_dbus_atomic_dec (&pending->refcount) == 1);
00177 
00178   if (last_unref)
00179     {
00180       /* If we get here, we should be already detached
00181        * from the connection, or never attached.
00182        */
00183       _dbus_assert (pending->connection == NULL);
00184       _dbus_assert (!pending->timeout_added);  
00185 
00186       /* this assumes we aren't holding connection lock... */
00187       _dbus_data_slot_list_free (&pending->slot_list);
00188       
00189       if (pending->timeout != NULL)
00190         _dbus_timeout_unref (pending->timeout);
00191       
00192       if (pending->timeout_link)
00193         {
00194           dbus_message_unref ((DBusMessage *)pending->timeout_link->data);
00195           _dbus_list_free_link (pending->timeout_link);
00196           pending->timeout_link = NULL;
00197         }
00198 
00199       if (pending->reply)
00200         {
00201           dbus_message_unref (pending->reply);
00202           pending->reply = NULL;
00203         }
00204       
00205       dbus_free (pending);
00206 
00207       dbus_pending_call_free_data_slot (&notify_user_data_slot);
00208     }
00209 }
00210 
00221 dbus_bool_t
00222 dbus_pending_call_set_notify (DBusPendingCall              *pending,
00223                               DBusPendingCallNotifyFunction function,
00224                               void                         *user_data,
00225                               DBusFreeFunction              free_user_data)
00226 {
00227   _dbus_return_val_if_fail (pending != NULL, FALSE);
00228 
00229   /* could invoke application code! */
00230   if (!dbus_pending_call_set_data (pending, notify_user_data_slot,
00231                                    user_data, free_user_data))
00232     return FALSE;
00233   
00234   pending->function = function;
00235 
00236   return TRUE;
00237 }
00238 
00248 void
00249 dbus_pending_call_cancel (DBusPendingCall *pending)
00250 {
00251   if (pending->connection)
00252     _dbus_connection_remove_pending_call (pending->connection,
00253                                           pending);
00254 }
00255 
00264 dbus_bool_t
00265 dbus_pending_call_get_completed (DBusPendingCall *pending)
00266 {
00267   return pending->completed;
00268 }
00269 
00279 DBusMessage*
00280 dbus_pending_call_steal_reply (DBusPendingCall *pending)
00281 {
00282   DBusMessage *message;
00283   
00284   _dbus_return_val_if_fail (pending->completed, NULL);
00285   _dbus_return_val_if_fail (pending->reply != NULL, NULL);
00286   
00287   message = pending->reply;
00288   pending->reply = NULL;
00289 
00290   return message;
00291 }
00292 
00307 void
00308 dbus_pending_call_block (DBusPendingCall *pending)
00309 {
00310   _dbus_connection_block_pending_call (pending);
00311 }
00312 
00313 static DBusDataSlotAllocator slot_allocator;
00314 _DBUS_DEFINE_GLOBAL_LOCK (pending_call_slots);
00315 
00330 dbus_bool_t
00331 dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p)
00332 {
00333   return _dbus_data_slot_allocator_alloc (&slot_allocator,
00334                                           _DBUS_LOCK_NAME (pending_call_slots),
00335                                           slot_p);
00336 }
00337 
00349 void
00350 dbus_pending_call_free_data_slot (dbus_int32_t *slot_p)
00351 {
00352   _dbus_return_if_fail (*slot_p >= 0);
00353   
00354   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
00355 }
00356 
00370 dbus_bool_t
00371 dbus_pending_call_set_data (DBusPendingCall  *pending,
00372                             dbus_int32_t      slot,
00373                             void             *data,
00374                             DBusFreeFunction  free_data_func)
00375 {
00376   DBusFreeFunction old_free_func;
00377   void *old_data;
00378   dbus_bool_t retval;
00379 
00380   _dbus_return_val_if_fail (pending != NULL, FALSE);
00381   _dbus_return_val_if_fail (slot >= 0, FALSE);
00382 
00383   retval = _dbus_data_slot_list_set (&slot_allocator,
00384                                      &pending->slot_list,
00385                                      slot, data, free_data_func,
00386                                      &old_free_func, &old_data);
00387 
00388   if (retval)
00389     {
00390       if (old_free_func)
00391         (* old_free_func) (old_data);
00392     }
00393 
00394   return retval;
00395 }
00396 
00405 void*
00406 dbus_pending_call_get_data (DBusPendingCall   *pending,
00407                             dbus_int32_t       slot)
00408 {
00409   void *res;
00410 
00411   _dbus_return_val_if_fail (pending != NULL, NULL);
00412 
00413   res = _dbus_data_slot_list_get (&slot_allocator,
00414                                   &pending->slot_list,
00415                                   slot);
00416 
00417   return res;
00418 }
00419 
00422 #ifdef DBUS_BUILD_TESTS
00423 
00430 dbus_bool_t
00431 _dbus_pending_call_test (const char *test_data_dir)
00432 {  
00433 
00434   return TRUE;
00435 }
00436 #endif /* DBUS_BUILD_TESTS */

Generated on Tue Sep 13 01:28:07 2005 for D-BUS by  doxygen 1.4.4