Add IgnoreOnIsolate=yes to dbus.service
[platform/upstream/dbus.git] / dbus / dbus-pending-call.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
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 2.1
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #include <config.h>
25 #include "dbus-internals.h"
26 #include "dbus-connection-internal.h"
27 #include "dbus-message-internal.h"
28 #include "dbus-pending-call-internal.h"
29 #include "dbus-pending-call.h"
30 #include "dbus-list.h"
31 #include "dbus-threads.h"
32 #include "dbus-test.h"
33
34 /**
35  * @defgroup DBusPendingCallInternals DBusPendingCall implementation details
36  * @ingroup DBusInternals
37  * @brief DBusPendingCall private implementation details.
38  *
39  * The guts of DBusPendingCall and its methods.
40  *
41  * @{
42  */
43
44 /**
45  * @brief Internals of DBusPendingCall
46  *
47  * Opaque object representing a reply message that we're waiting for.
48  */
49
50 /**
51  * shorter and more visible way to write _dbus_connection_lock()
52  */
53 #define CONNECTION_LOCK(connection)   _dbus_connection_lock(connection)
54 /**
55  * shorter and more visible way to write _dbus_connection_unlock()
56  */
57 #define CONNECTION_UNLOCK(connection) _dbus_connection_unlock(connection)
58
59 /**
60  * Implementation details of #DBusPendingCall - all fields are private.
61  */
62 struct DBusPendingCall
63 {
64   DBusAtomic refcount;                            /**< reference count */
65
66   DBusDataSlotList slot_list;                     /**< Data stored by allocated integer ID */
67   
68   DBusPendingCallNotifyFunction function;         /**< Notifier when reply arrives. */
69
70   DBusConnection *connection;                     /**< Connections we're associated with */
71   DBusMessage *reply;                             /**< Reply (after we've received it) */
72   DBusTimeout *timeout;                           /**< Timeout */
73
74   DBusList *timeout_link;                         /**< Preallocated timeout response */
75   
76   dbus_uint32_t reply_serial;                     /**< Expected serial of reply */
77
78   /**
79    * TRUE if some thread has taken responsibility for completing this
80    * pending call: either the pending call has completed, or it is about
81    * to be completed. Protected by the connection lock.
82    */
83   unsigned int completed : 1;
84   /**
85    * TRUE if we have added the timeout. Protected by the connection lock.
86    */
87   unsigned int timeout_added : 1;
88 };
89
90 static void
91 _dbus_pending_call_trace_ref (DBusPendingCall *pending_call,
92     int old_refcount,
93     int new_refcount,
94     const char *why)
95 {
96 #ifdef DBUS_ENABLE_VERBOSE_MODE
97   static int enabled = -1;
98
99   _dbus_trace_ref ("DBusPendingCall", pending_call, old_refcount,
100       new_refcount, why, "DBUS_PENDING_CALL_TRACE", &enabled);
101 #endif
102 }
103
104 static dbus_int32_t notify_user_data_slot = -1;
105
106 /**
107  * Creates a new pending reply object.
108  *
109  * @param connection connection where reply will arrive
110  * @param timeout_milliseconds length of timeout, -1 (or
111  *  #DBUS_TIMEOUT_USE_DEFAULT) for default,
112  *  #DBUS_TIMEOUT_INFINITE for no timeout
113  * @param timeout_handler timeout handler, takes pending call as data
114  * @returns a new #DBusPendingCall or #NULL if no memory.
115  */
116 DBusPendingCall*
117 _dbus_pending_call_new_unlocked (DBusConnection    *connection,
118                                  int                timeout_milliseconds,
119                                  DBusTimeoutHandler timeout_handler)
120 {
121   DBusPendingCall *pending;
122   DBusTimeout *timeout;
123
124   _dbus_assert (timeout_milliseconds >= 0 || timeout_milliseconds == -1);
125  
126   if (timeout_milliseconds == -1)
127     timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE;
128
129   if (!dbus_pending_call_allocate_data_slot (&notify_user_data_slot))
130     return NULL;
131   
132   pending = dbus_new0 (DBusPendingCall, 1);
133   
134   if (pending == NULL)
135     {
136       dbus_pending_call_free_data_slot (&notify_user_data_slot);
137       return NULL;
138     }
139
140   if (timeout_milliseconds != DBUS_TIMEOUT_INFINITE)
141     {
142       timeout = _dbus_timeout_new (timeout_milliseconds,
143                                    timeout_handler,
144                                    pending, NULL);  
145
146       if (timeout == NULL)
147         {
148           dbus_pending_call_free_data_slot (&notify_user_data_slot);
149           dbus_free (pending);
150           return NULL;
151         }
152
153       pending->timeout = timeout;
154     }
155   else
156     {
157       pending->timeout = NULL;
158     }
159
160   _dbus_atomic_inc (&pending->refcount);
161   pending->connection = connection;
162   _dbus_connection_ref_unlocked (pending->connection);
163
164   _dbus_data_slot_list_init (&pending->slot_list);
165
166   _dbus_pending_call_trace_ref (pending, 0, 1, "new_unlocked");
167
168   return pending;
169 }
170
171 /**
172  * Sets the reply of a pending call with the given message,
173  * or if the message is #NULL, by timing out the pending call.
174  * 
175  * @param pending the pending call
176  * @param message the message to complete the call with, or #NULL
177  *  to time out the call
178  */
179 void
180 _dbus_pending_call_set_reply_unlocked (DBusPendingCall *pending,
181                                        DBusMessage     *message)
182 {
183   if (message == NULL)
184     {
185       message = pending->timeout_link->data;
186       _dbus_list_clear (&pending->timeout_link);
187     }
188   else
189     dbus_message_ref (message);
190
191   _dbus_verbose ("  handing message %p (%s) to pending call serial %u\n",
192                  message,
193                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN ?
194                  "method return" :
195                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ?
196                  "error" : "other type",
197                  pending->reply_serial);
198   
199   _dbus_assert (pending->reply == NULL);
200   _dbus_assert (pending->reply_serial == dbus_message_get_reply_serial (message));
201   pending->reply = message;
202 }
203
204 /**
205  * Sets the pending call to completed
206  *
207  * This method is called with the connection lock held, to protect
208  * pending->completed. It must be paired with a call to
209  * _dbus_pending_call_finish_completion() after the connection lock has
210  * been released.
211  *
212  * @param pending the pending call
213  */
214 void
215 _dbus_pending_call_start_completion_unlocked (DBusPendingCall *pending)
216 {
217   _dbus_assert (!pending->completed);
218   
219   pending->completed = TRUE;
220 }
221
222 /**
223  * Call the notifier function for the pending call.
224  *
225  * This method must be called after the connection lock has been
226  * released, and must be paired with a call to
227  * _dbus_pending_call_start_completion_unlocked().
228  *
229  * @param pending the pending call
230  */
231 void
232 _dbus_pending_call_finish_completion (DBusPendingCall *pending)
233 {
234   _dbus_assert (pending->completed);
235
236   if (pending->function)
237     {
238       void *user_data;
239       user_data = dbus_pending_call_get_data (pending,
240                                               notify_user_data_slot);
241       
242       (* pending->function) (pending, user_data);
243     }
244 }
245
246 /**
247  * If the pending call hasn't been timed out, add its timeout
248  * error reply to the connection's incoming message queue.
249  *
250  * @param pending the pending call
251  * @param connection the connection the call was sent to
252  */
253 void
254 _dbus_pending_call_queue_timeout_error_unlocked (DBusPendingCall *pending, 
255                                                  DBusConnection  *connection)
256 {
257   _dbus_assert (connection == pending->connection);
258   
259   if (pending->timeout_link)
260     {
261       _dbus_connection_queue_synthesized_message_link (connection,
262                                                        pending->timeout_link);
263       pending->timeout_link = NULL;
264     }
265 }
266
267 /**
268  * Checks to see if a timeout has been added
269  *
270  * @param pending the pending_call
271  * @returns #TRUE if there is a timeout or #FALSE if not
272  */
273 dbus_bool_t 
274 _dbus_pending_call_is_timeout_added_unlocked (DBusPendingCall  *pending)
275 {
276   _dbus_assert (pending != NULL);
277
278   return pending->timeout_added;
279 }
280
281
282 /**
283  * Sets wether the timeout has been added
284  *
285  * @param pending the pending_call
286  * @param is_added whether or not a timeout is added
287  */
288 void
289 _dbus_pending_call_set_timeout_added_unlocked (DBusPendingCall  *pending,
290                                                dbus_bool_t       is_added)
291 {
292   _dbus_assert (pending != NULL);
293
294   pending->timeout_added = is_added;
295 }
296
297
298 /**
299  * Retrives the timeout
300  *
301  * @param pending the pending_call
302  * @returns a timeout object or NULL if call has no timeout
303  */
304 DBusTimeout *
305 _dbus_pending_call_get_timeout_unlocked (DBusPendingCall  *pending)
306 {
307   _dbus_assert (pending != NULL);
308
309   return pending->timeout;
310 }
311
312 /**
313  * Gets the reply's serial number
314  *
315  * @param pending the pending_call
316  * @returns a serial number for the reply or 0 
317  */
318 dbus_uint32_t 
319 _dbus_pending_call_get_reply_serial_unlocked (DBusPendingCall  *pending)
320 {
321   _dbus_assert (pending != NULL);
322
323   return pending->reply_serial;
324 }
325
326 /**
327  * Sets the reply's serial number
328  *
329  * @param pending the pending_call
330  * @param serial the serial number 
331  */
332 void
333 _dbus_pending_call_set_reply_serial_unlocked  (DBusPendingCall *pending,
334                                                dbus_uint32_t serial)
335 {
336   _dbus_assert (pending != NULL);
337   _dbus_assert (pending->reply_serial == 0);
338
339   pending->reply_serial = serial;
340 }
341
342 /**
343  * Gets the connection associated with this pending call.
344  *
345  * @param pending the pending_call
346  * @returns the connection associated with the pending call
347  */
348 DBusConnection *
349 _dbus_pending_call_get_connection_and_lock (DBusPendingCall *pending)
350 {
351   _dbus_assert (pending != NULL);
352  
353   CONNECTION_LOCK (pending->connection);
354   return pending->connection;
355 }
356
357 /**
358  * Gets the connection associated with this pending call.
359  *
360  * @param pending the pending_call
361  * @returns the connection associated with the pending call
362  */
363 DBusConnection *
364 _dbus_pending_call_get_connection_unlocked (DBusPendingCall *pending)
365 {
366   _dbus_assert (pending != NULL);
367  
368   return pending->connection;
369 }
370
371 /**
372  * Sets the reply message associated with the pending call to a timeout error
373  *
374  * @param pending the pending_call
375  * @param message the message we are sending the error reply to 
376  * @param serial serial number for the reply
377  * @return #FALSE on OOM
378  */
379 dbus_bool_t
380 _dbus_pending_call_set_timeout_error_unlocked (DBusPendingCall *pending,
381                                                DBusMessage     *message,
382                                                dbus_uint32_t    serial)
383
384   DBusList *reply_link;
385   DBusMessage *reply;
386
387   reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
388                                   "Did not receive a reply. Possible causes include: "
389                                   "the remote application did not send a reply, "
390                                   "the message bus security policy blocked the reply, "
391                                   "the reply timeout expired, or "
392                                   "the network connection was broken.");
393   if (reply == NULL)
394     return FALSE;
395
396   /* FIXME - lock may now fail */
397   dbus_message_lock (reply);
398
399   reply_link = _dbus_list_alloc_link (reply);
400   if (reply_link == NULL)
401     {
402       /* it's OK to unref this, nothing that could have attached a callback
403        * has ever seen it */
404       dbus_message_unref (reply);
405       return FALSE;
406     }
407
408   pending->timeout_link = reply_link;
409
410   _dbus_pending_call_set_reply_serial_unlocked (pending, serial);
411   
412   return TRUE;
413 }
414
415 /**
416  * Increments the reference count on a pending call,
417  * while the lock on its connection is already held.
418  *
419  * @param pending the pending call object
420  * @returns the pending call object
421  */
422 DBusPendingCall *
423 _dbus_pending_call_ref_unlocked (DBusPendingCall *pending)
424 {
425   dbus_int32_t old_refcount;
426
427   old_refcount = _dbus_atomic_inc (&pending->refcount);
428   _dbus_pending_call_trace_ref (pending, old_refcount, old_refcount + 1,
429       "ref_unlocked");
430
431   return pending;
432 }
433
434
435 static void
436 _dbus_pending_call_last_unref (DBusPendingCall *pending)
437 {
438   DBusConnection *connection;
439   
440   /* If we get here, we should be already detached
441    * from the connection, or never attached.
442    */
443   _dbus_assert (!pending->timeout_added);  
444
445   connection = pending->connection;
446
447   /* this assumes we aren't holding connection lock... */
448   _dbus_data_slot_list_free (&pending->slot_list);
449
450   if (pending->timeout != NULL)
451     _dbus_timeout_unref (pending->timeout);
452       
453   if (pending->timeout_link)
454     {
455       dbus_message_unref ((DBusMessage *)pending->timeout_link->data);
456       _dbus_list_free_link (pending->timeout_link);
457       pending->timeout_link = NULL;
458     }
459
460   if (pending->reply)
461     {
462       dbus_message_unref (pending->reply);
463       pending->reply = NULL;
464     }
465       
466   dbus_free (pending);
467
468   dbus_pending_call_free_data_slot (&notify_user_data_slot);
469
470   /* connection lock should not be held. */
471   /* Free the connection last to avoid a weird state while
472    * calling out to application code where the pending exists
473    * but not the connection.
474    */
475   dbus_connection_unref (connection);
476 }
477
478 /**
479  * Decrements the reference count on a pending call,
480  * freeing it if the count reaches 0. Assumes
481  * connection lock is already held.
482  *
483  * @param pending the pending call object
484  */
485 void
486 _dbus_pending_call_unref_and_unlock (DBusPendingCall *pending)
487 {
488   dbus_int32_t old_refcount;
489
490   old_refcount = _dbus_atomic_dec (&pending->refcount);
491   _dbus_assert (old_refcount > 0);
492   _dbus_pending_call_trace_ref (pending, old_refcount,
493       old_refcount - 1, "unref_and_unlock");
494
495   CONNECTION_UNLOCK (pending->connection);
496
497   if (old_refcount == 1)
498     _dbus_pending_call_last_unref (pending);
499 }
500
501 /**
502  * Checks whether the pending call has received a reply
503  * yet, or not. Assumes connection lock is held.
504  *
505  * @param pending the pending call
506  * @returns #TRUE if a reply has been received
507  */
508 dbus_bool_t
509 _dbus_pending_call_get_completed_unlocked (DBusPendingCall    *pending)
510 {
511   return pending->completed;
512 }
513
514 static DBusDataSlotAllocator slot_allocator =
515   _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (pending_call_slots));
516
517 /**
518  * Stores a pointer on a #DBusPendingCall, along
519  * with an optional function to be used for freeing
520  * the data when the data is set again, or when
521  * the pending call is finalized. The slot number
522  * must have been allocated with dbus_pending_call_allocate_data_slot().
523  *
524  * @param pending the pending_call
525  * @param slot the slot number
526  * @param data the data to store
527  * @param free_data_func finalizer function for the data
528  * @returns #TRUE if there was enough memory to store the data
529  */
530 dbus_bool_t
531 _dbus_pending_call_set_data_unlocked (DBusPendingCall  *pending,
532                                      dbus_int32_t      slot,
533                                      void             *data,
534                                      DBusFreeFunction  free_data_func)
535 {
536   DBusFreeFunction old_free_func;
537   void *old_data;
538   dbus_bool_t retval;
539
540   retval = _dbus_data_slot_list_set (&slot_allocator,
541                                      &pending->slot_list,
542                                      slot, data, free_data_func,
543                                      &old_free_func, &old_data);
544
545   /* Drop locks to call out to app code */
546   CONNECTION_UNLOCK (pending->connection);
547   
548   if (retval)
549     {
550       if (old_free_func)
551         (* old_free_func) (old_data);
552     }
553
554   CONNECTION_LOCK (pending->connection);
555   
556   return retval;
557 }
558
559 /** @} */
560
561 /**
562  * @defgroup DBusPendingCall DBusPendingCall
563  * @ingroup  DBus
564  * @brief Pending reply to a method call message
565  *
566  * A DBusPendingCall is an object representing an
567  * expected reply. A #DBusPendingCall can be created
568  * when you send a message that should have a reply.
569  *
570  * @{
571  */
572
573 /**
574  * @def DBUS_TIMEOUT_INFINITE
575  *
576  * An integer constant representing an infinite timeout. This has the
577  * numeric value 0x7fffffff (the largest 32-bit signed integer).
578  *
579  * For source compatibility with D-Bus versions earlier than 1.4.12, use
580  * 0x7fffffff, or INT32_MAX (assuming your platform has it).
581  */
582
583 /**
584  * @def DBUS_TIMEOUT_USE_DEFAULT
585  *
586  * An integer constant representing a request to use the default timeout.
587  * This has numeric value -1.
588  *
589  * For source compatibility with D-Bus versions earlier than 1.4.12, use a
590  * literal -1.
591  */
592
593 /**
594  * @typedef DBusPendingCall
595  *
596  * Opaque data type representing a message pending.
597  */
598
599 /**
600  * Increments the reference count on a pending call.
601  *
602  * @param pending the pending call object
603  * @returns the pending call object
604  */
605 DBusPendingCall *
606 dbus_pending_call_ref (DBusPendingCall *pending)
607 {
608   dbus_int32_t old_refcount;
609
610   _dbus_return_val_if_fail (pending != NULL, NULL);
611
612   old_refcount = _dbus_atomic_inc (&pending->refcount);
613   _dbus_pending_call_trace_ref (pending, old_refcount, old_refcount + 1,
614       "ref");
615
616   return pending;
617 }
618
619 /**
620  * Decrements the reference count on a pending call,
621  * freeing it if the count reaches 0.
622  *
623  * @param pending the pending call object
624  */
625 void
626 dbus_pending_call_unref (DBusPendingCall *pending)
627 {
628   dbus_int32_t old_refcount;
629
630   _dbus_return_if_fail (pending != NULL);
631
632   old_refcount = _dbus_atomic_dec (&pending->refcount);
633   _dbus_pending_call_trace_ref (pending, old_refcount, old_refcount - 1,
634       "unref");
635
636   if (old_refcount == 1)
637     _dbus_pending_call_last_unref(pending);
638 }
639
640 /**
641  * Sets a notification function to be called when the reply is
642  * received or the pending call times out.
643  *
644  * @param pending the pending call
645  * @param function notifier function
646  * @param user_data data to pass to notifier function
647  * @param free_user_data function to free the user data
648  * @returns #FALSE if not enough memory
649  */
650 dbus_bool_t
651 dbus_pending_call_set_notify (DBusPendingCall              *pending,
652                               DBusPendingCallNotifyFunction function,
653                               void                         *user_data,
654                               DBusFreeFunction              free_user_data)
655 {
656   dbus_bool_t ret = FALSE;
657
658   _dbus_return_val_if_fail (pending != NULL, FALSE);
659
660   CONNECTION_LOCK (pending->connection);
661   
662   /* could invoke application code! */
663   if (!_dbus_pending_call_set_data_unlocked (pending, notify_user_data_slot,
664                                              user_data, free_user_data))
665     goto out;
666   
667   pending->function = function;
668   ret = TRUE;
669
670 out:
671   CONNECTION_UNLOCK (pending->connection);
672   
673   return ret;
674 }
675
676 /**
677  * Cancels the pending call, such that any reply or error received
678  * will just be ignored.  Drops the dbus library's internal reference
679  * to the #DBusPendingCall so will free the call if nobody else is
680  * holding a reference. However you usually get a reference from
681  * dbus_connection_send_with_reply() so probably your app owns a ref
682  * also.
683  *
684  * Note that canceling a pending call will <em>not</em> simulate a
685  * timed-out call; if a call times out, then a timeout error reply is
686  * received. If you cancel the call, no reply is received unless the
687  * the reply was already received before you canceled.
688  * 
689  * @param pending the pending call
690  */
691 void
692 dbus_pending_call_cancel (DBusPendingCall *pending)
693 {
694   _dbus_return_if_fail (pending != NULL);
695
696   _dbus_connection_remove_pending_call (pending->connection,
697                                         pending);
698 }
699
700 /**
701  * Checks whether the pending call has received a reply
702  * yet, or not.
703  *
704  * @param pending the pending call
705  * @returns #TRUE if a reply has been received
706  */
707 dbus_bool_t
708 dbus_pending_call_get_completed (DBusPendingCall *pending)
709 {
710   dbus_bool_t completed;
711   
712   _dbus_return_val_if_fail (pending != NULL, FALSE);
713
714   CONNECTION_LOCK (pending->connection);
715   completed = pending->completed;
716   CONNECTION_UNLOCK (pending->connection);
717
718   return completed;
719 }
720
721 /**
722  * Gets the reply, or returns #NULL if none has been received
723  * yet. Ownership of the reply message passes to the caller. This
724  * function can only be called once per pending call, since the reply
725  * message is tranferred to the caller.
726  * 
727  * @param pending the pending call
728  * @returns the reply message or #NULL.
729  */
730 DBusMessage*
731 dbus_pending_call_steal_reply (DBusPendingCall *pending)
732 {
733   DBusMessage *message;
734   
735   _dbus_return_val_if_fail (pending != NULL, NULL);
736   _dbus_return_val_if_fail (pending->completed, NULL);
737   _dbus_return_val_if_fail (pending->reply != NULL, NULL);
738
739   CONNECTION_LOCK (pending->connection);
740   
741   message = pending->reply;
742   pending->reply = NULL;
743
744   CONNECTION_UNLOCK (pending->connection);
745
746   _dbus_message_trace_ref (message, -1, -1, "dbus_pending_call_steal_reply");
747   return message;
748 }
749
750 /**
751  * Block until the pending call is completed.  The blocking is as with
752  * dbus_connection_send_with_reply_and_block(); it does not enter the
753  * main loop or process other messages, it simply waits for the reply
754  * in question.
755  *
756  * If the pending call is already completed, this function returns
757  * immediately.
758  *
759  * @todo when you start blocking, the timeout is reset, but it should
760  * really only use time remaining since the pending call was created.
761  * This requires storing timestamps instead of intervals in the timeout
762  *
763  * @param pending the pending call
764  */
765 void
766 dbus_pending_call_block (DBusPendingCall *pending)
767 {
768   _dbus_return_if_fail (pending != NULL);
769
770   _dbus_connection_block_pending_call (pending);
771 }
772
773 /**
774  * Allocates an integer ID to be used for storing application-specific
775  * data on any DBusPendingCall. The allocated ID may then be used
776  * with dbus_pending_call_set_data() and dbus_pending_call_get_data().
777  * The passed-in slot must be initialized to -1, and is filled in
778  * with the slot ID. If the passed-in slot is not -1, it's assumed
779  * to be already allocated, and its refcount is incremented.
780  * 
781  * The allocated slot is global, i.e. all DBusPendingCall objects will
782  * have a slot with the given integer ID reserved.
783  *
784  * @param slot_p address of a global variable storing the slot
785  * @returns #FALSE on failure (no memory)
786  */
787 dbus_bool_t
788 dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p)
789 {
790   _dbus_return_val_if_fail (slot_p != NULL, FALSE);
791
792   return _dbus_data_slot_allocator_alloc (&slot_allocator,
793                                           slot_p);
794 }
795
796 /**
797  * Deallocates a global ID for #DBusPendingCall data slots.
798  * dbus_pending_call_get_data() and dbus_pending_call_set_data() may
799  * no longer be used with this slot.  Existing data stored on existing
800  * DBusPendingCall objects will be freed when the #DBusPendingCall is
801  * finalized, but may not be retrieved (and may only be replaced if
802  * someone else reallocates the slot).  When the refcount on the
803  * passed-in slot reaches 0, it is set to -1.
804  *
805  * @param slot_p address storing the slot to deallocate
806  */
807 void
808 dbus_pending_call_free_data_slot (dbus_int32_t *slot_p)
809 {
810   _dbus_return_if_fail (slot_p != NULL);
811   _dbus_return_if_fail (*slot_p >= 0);
812
813   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
814 }
815
816 /**
817  * Stores a pointer on a #DBusPendingCall, along
818  * with an optional function to be used for freeing
819  * the data when the data is set again, or when
820  * the pending call is finalized. The slot number
821  * must have been allocated with dbus_pending_call_allocate_data_slot().
822  *
823  * @param pending the pending_call
824  * @param slot the slot number
825  * @param data the data to store
826  * @param free_data_func finalizer function for the data
827  * @returns #TRUE if there was enough memory to store the data
828  */
829 dbus_bool_t
830 dbus_pending_call_set_data (DBusPendingCall  *pending,
831                             dbus_int32_t      slot,
832                             void             *data,
833                             DBusFreeFunction  free_data_func)
834 {
835   dbus_bool_t retval;
836   
837   _dbus_return_val_if_fail (pending != NULL, FALSE);
838   _dbus_return_val_if_fail (slot >= 0, FALSE);
839
840   
841   CONNECTION_LOCK (pending->connection);
842   retval = _dbus_pending_call_set_data_unlocked (pending, slot, data, free_data_func);
843   CONNECTION_UNLOCK (pending->connection);
844   return retval;
845 }
846
847 /**
848  * Retrieves data previously set with dbus_pending_call_set_data().
849  * The slot must still be allocated (must not have been freed).
850  *
851  * @param pending the pending_call
852  * @param slot the slot to get data from
853  * @returns the data, or #NULL if not found
854  */
855 void*
856 dbus_pending_call_get_data (DBusPendingCall   *pending,
857                             dbus_int32_t       slot)
858 {
859   void *res;
860
861   _dbus_return_val_if_fail (pending != NULL, NULL);
862
863   CONNECTION_LOCK (pending->connection);
864   res = _dbus_data_slot_list_get (&slot_allocator,
865                                   &pending->slot_list,
866                                   slot);
867   CONNECTION_UNLOCK (pending->connection);
868
869   return res;
870 }
871
872 /** @} */