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 2.0
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 
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       /* If we get here, we should be already detached
00171        * from the connection, or never attached.
00172        */
00173       _dbus_assert (pending->connection == NULL);
00174       _dbus_assert (!pending->timeout_added);  
00175 
00176       /* this assumes we aren't holding connection lock... */
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 (&notify_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   /* could invoke application code! */
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   /* message may be NULL if no reply */
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 /* DBUS_BUILD_TESTS */

Generated on Wed Jun 9 05:01:26 2004 for D-BUS by doxygen1.2.15