void
bus_expire_list_free (BusExpireList *list)
{
  _dbus_assert (list->items == NULL);

  _dbus_loop_remove_timeout (list->loop, list->timeout);

  _dbus_timeout_unref (list->timeout);

  dbus_free (list);
}
/**
 * Removes a timeout from the timeout list, invoking the
 * application's DBusRemoveTimeoutFunction if appropriate.
 *
 * @param timeout_list the timeout list.
 * @param timeout the timeout to remove.
 */
void
_dbus_timeout_list_remove_timeout (DBusTimeoutList *timeout_list,
				   DBusTimeout     *timeout)
{
  if (!_dbus_list_remove (&timeout_list->timeouts, timeout))
    _dbus_assert_not_reached ("Nonexistent timeout was removed");

  if (timeout_list->remove_timeout_function != NULL)
    (* timeout_list->remove_timeout_function) (timeout,
					       timeout_list->timeout_data);

  _dbus_timeout_unref (timeout);
}
static void
_dbus_pending_call_last_unref (DBusPendingCall *pending)
{
  DBusConnection *connection;
  
  /* If we get here, we should be already detached
   * from the connection, or never attached.
   */
  _dbus_assert (!pending->timeout_added);  

  connection = pending->connection;

  /* this assumes we aren't holding connection lock... */
  _dbus_data_slot_list_free (&pending->slot_list);

  if (pending->timeout != NULL)
    _dbus_timeout_unref (pending->timeout);
      
  if (pending->timeout_link)
    {
      dbus_message_unref ((DBusMessage *)pending->timeout_link->data);
      _dbus_list_free_link (pending->timeout_link);
      pending->timeout_link = NULL;
    }

  if (pending->reply)
    {
      dbus_message_unref (pending->reply);
      pending->reply = NULL;
    }
      
  dbus_free (pending);

  dbus_pending_call_free_data_slot (&notify_user_data_slot);

  /* connection lock should not be held. */
  /* Free the connection last to avoid a weird state while
   * calling out to application code where the pending exists
   * but not the connection.
   */
  dbus_connection_unref (connection);
}
BusExpireList*
bus_expire_list_new (DBusLoop      *loop,
                     int            expire_after,
                     BusExpireFunc  expire_func,
                     void          *data)
{
  BusExpireList *list;

  list = dbus_new0 (BusExpireList, 1);
  if (list == NULL)
    return NULL;

  list->expire_func = expire_func;
  list->data = data;
  list->loop = loop;
  list->expire_after = expire_after;

  list->timeout = _dbus_timeout_new (100, /* irrelevant */
                                     expire_timeout_handler,
                                     list, NULL);
  if (list->timeout == NULL)
    goto failed;

  _dbus_timeout_set_enabled (list->timeout, FALSE);

  if (!_dbus_loop_add_timeout (list->loop,
                               list->timeout,
                               call_timeout_callback, NULL, NULL))
    goto failed;

  return list;

 failed:
  if (list->timeout)
    _dbus_timeout_unref (list->timeout);

  dbus_free (list);

  return NULL;
}
/**
 * Adds a new timeout to the timeout list, invoking the
 * application DBusAddTimeoutFunction if appropriate.
 *
 * @param timeout_list the timeout list.
 * @param timeout the timeout to add.
 * @returns #TRUE on success, #FALSE If no memory.
 */
dbus_bool_t
_dbus_timeout_list_add_timeout (DBusTimeoutList *timeout_list,
				DBusTimeout     *timeout)
{
  if (!_dbus_list_append (&timeout_list->timeouts, timeout))
    return FALSE;

  _dbus_timeout_ref (timeout);

  if (timeout_list->add_timeout_function != NULL)
    {
      if (!(* timeout_list->add_timeout_function) (timeout,
                                                   timeout_list->timeout_data))
        {
          _dbus_list_remove_last (&timeout_list->timeouts, timeout);
          _dbus_timeout_unref (timeout);
          return FALSE;
        }
    }

  return TRUE;
}