diff options
| author | Havoc Pennington <hp@redhat.com> | 2003-08-15 23:10:12 +0000 | 
|---|---|---|
| committer | Havoc Pennington <hp@redhat.com> | 2003-08-15 23:10:12 +0000 | 
| commit | a1b0bd33408f03894987ac32b4e6b46c6a15a594 (patch) | |
| tree | 2903a89983ce0efa1d3480b5d76322a325e621da | |
| parent | ef614207fc4f03e5cc02faeb109f739eb1ccdf31 (diff) | |
2003-08-15  Havoc Pennington  <hp@redhat.com>
	* dbus/dbus-pending-call.c (dbus_pending_call_block): implement
	* dbus/dbus-connection.c
	(dbus_connection_send_with_reply_and_block): factor out internals;
	change to convert any error replies to DBusError instead of
	returning them as a message
| -rw-r--r-- | ChangeLog | 9 | ||||
| -rw-r--r-- | dbus/dbus-connection-internal.h | 9 | ||||
| -rw-r--r-- | dbus/dbus-connection.c | 161 | ||||
| -rw-r--r-- | dbus/dbus-pending-call.c | 25 | ||||
| -rw-r--r-- | dbus/dbus-pending-call.h | 1 | ||||
| -rw-r--r-- | glib/dbus-gproxy.h | 70 | 
6 files changed, 191 insertions, 84 deletions
@@ -1,3 +1,12 @@ +2003-08-15  Havoc Pennington  <hp@redhat.com> + +	* dbus/dbus-pending-call.c (dbus_pending_call_block): implement + +	* dbus/dbus-connection.c +	(dbus_connection_send_with_reply_and_block): factor out internals; +	change to convert any error replies to DBusError instead of  +	returning them as a message +  2003-08-15  Havoc Pennington  <hp@pobox.com>  	* dbus/dbus-connection.c,  diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h index d9d5c5b4..f26c92e6 100644 --- a/dbus/dbus-connection-internal.h +++ b/dbus/dbus-connection-internal.h @@ -88,15 +88,18 @@ DBusHandlerResult _dbus_message_handler_handle_message         (DBusMessageHandl                                                                  DBusMessage        *message);  void              _dbus_connection_init_id                     (DBusConnection     *connection,                                                                  DBusObjectID       *id); -  DBusPendingCall*  _dbus_pending_call_new                       (DBusConnection     *connection,                                                                  int                 timeout_milliseconds,                                                                  DBusTimeoutHandler  timeout_handler); -  void              _dbus_pending_call_notify                    (DBusPendingCall    *pending); -  void              _dbus_connection_remove_pending_call         (DBusConnection     *connection,                                                                  DBusPendingCall    *pending); +DBusMessage*      _dbus_connection_block_for_reply             (DBusConnection     *connection, +                                                                dbus_uint32_t       client_serial, +                                                                int                 timeout_milliseconds); +void              _dbus_pending_call_complete_and_unlock       (DBusPendingCall    *pending, +                                                                DBusMessage        *message); +  /**   * @addtogroup DBusPendingCallInternals DBusPendingCall implementation details diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 3af00ed0..bc26a3ec 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -621,6 +621,38 @@ _dbus_connection_remove_pending_call (DBusConnection  *connection,  }  /** + * Completes a pending call with the given message, + * or if the message is #NULL, by timing out the pending call. + *  + * @param pending the pending call + * @param message the message to complete the call with, or #NULL + *  to time out the call + */ +void +_dbus_pending_call_complete_and_unlock (DBusPendingCall *pending, +                                        DBusMessage     *message) +{ +  if (message == NULL) +    { +      message = pending->timeout_link->data; +      _dbus_list_clear (&pending->timeout_link); +    } + +  _dbus_verbose ("  handing message %p to pending call\n", message); +   +  _dbus_assert (pending->reply == NULL); +  pending->reply = message; +  dbus_message_ref (pending->reply); +   +  dbus_pending_call_ref (pending); /* in case there's no app with a ref held */ +  _dbus_connection_detach_pending_call_and_unlock (pending->connection, pending); +   +  /* Must be called unlocked since it invokes app callback */ +  _dbus_pending_call_notify (pending); +  dbus_pending_call_unref (pending); +} + +/**   * Acquire the transporter I/O path. This must be done before   * doing any I/O in the transporter. May sleep and drop the   * connection mutex while waiting for the I/O path. @@ -1745,42 +1777,31 @@ check_for_reply_unlocked (DBusConnection *connection,  }  /** - * Sends a message and blocks a certain time period while waiting for a reply. - * This function does not dispatch any message handlers until the main loop - * has been reached. This function is used to do non-reentrant "method calls." - * If a reply is received, it is returned, and removed from the incoming - * message queue. If it is not received, #NULL is returned and the - * error is set to #DBUS_ERROR_NO_REPLY. If something else goes - * wrong, result is set to whatever is appropriate, such as - * #DBUS_ERROR_NO_MEMORY or #DBUS_ERROR_DISCONNECTED. + * Blocks a certain time period while waiting for a reply. + * If no reply arrives, returns #NULL.   *   * @todo could use performance improvements (it keeps scanning   * the whole message queue for example) and has thread issues,   * see comments in source   *   * @param connection the connection - * @param message the message to send + * @param client_serial the reply serial to wait for   * @param timeout_milliseconds timeout in milliseconds or -1 for default - * @param error return location for error message - * @returns the message that is the reply or #NULL with an error code if the - * function fails. + * @returns the message that is the reply or #NULL if no reply   */ -DBusMessage * -dbus_connection_send_with_reply_and_block (DBusConnection     *connection, -                                           DBusMessage        *message, -                                           int                 timeout_milliseconds, -                                           DBusError          *error) +DBusMessage* +_dbus_connection_block_for_reply (DBusConnection     *connection, +                                  dbus_uint32_t       client_serial, +                                  int                 timeout_milliseconds)  { -  dbus_uint32_t client_serial;    long start_tv_sec, start_tv_usec;    long end_tv_sec, end_tv_usec;    long tv_sec, tv_usec;    DBusDispatchStatus status;    _dbus_return_val_if_fail (connection != NULL, NULL); -  _dbus_return_val_if_fail (message != NULL, NULL); -  _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);   -  _dbus_return_val_if_error_is_set (error, NULL); +  _dbus_return_val_if_fail (client_serial != 0, NULL); +  _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);    if (timeout_milliseconds == -1)      timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE; @@ -1792,14 +1813,6 @@ dbus_connection_send_with_reply_and_block (DBusConnection     *connection,    if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6)      timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6; -  if (!dbus_connection_send (connection, message, &client_serial)) -    { -      _DBUS_SET_OOM (error); -      return NULL; -    } - -  message = NULL; -      /* Flush message queue */    dbus_connection_flush (connection); @@ -1894,11 +1907,6 @@ dbus_connection_send_with_reply_and_block (DBusConnection     *connection,    _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",                   (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000); -   -  if (dbus_connection_get_is_connected (connection)) -    dbus_set_error (error, DBUS_ERROR_NO_REPLY, "Message did not receive a reply"); -  else -    dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Disconnected prior to receiving a reply");    /* unlocks and calls out to user code */    _dbus_connection_update_dispatch_status_and_unlock (connection, status); @@ -1907,6 +1915,70 @@ dbus_connection_send_with_reply_and_block (DBusConnection     *connection,  }  /** + * Sends a message and blocks a certain time period while waiting for + * a reply.  This function does not reenter the main loop, + * i.e. messages other than the reply are queued up but not + * processed. This function is used to do non-reentrant "method + * calls." + *  + * If a normal reply is received, it is returned, and removed from the + * incoming message queue. If it is not received, #NULL is returned + * and the error is set to #DBUS_ERROR_NO_REPLY.  If an error reply is + * received, it is converted to a #DBusError and returned as an error, + * then the reply message is deleted. If something else goes wrong, + * result is set to whatever is appropriate, such as + * #DBUS_ERROR_NO_MEMORY or #DBUS_ERROR_DISCONNECTED. + * + * @param connection the connection + * @param message the message to send + * @param timeout_milliseconds timeout in milliseconds or -1 for default + * @param error return location for error message + * @returns the message that is the reply or #NULL with an error code if the + * function fails. + */ +DBusMessage * +dbus_connection_send_with_reply_and_block (DBusConnection     *connection, +                                           DBusMessage        *message, +                                           int                 timeout_milliseconds, +                                           DBusError          *error) +{ +  dbus_uint32_t client_serial; +  DBusMessage *reply; +   +  _dbus_return_val_if_fail (connection != NULL, NULL); +  _dbus_return_val_if_fail (message != NULL, NULL); +  _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);   +  _dbus_return_val_if_error_is_set (error, NULL); +   +  if (!dbus_connection_send (connection, message, &client_serial)) +    { +      _DBUS_SET_OOM (error); +      return NULL; +    } + +  reply = _dbus_connection_block_for_reply (connection, +                                            client_serial, +                                            timeout_milliseconds); +   +  if (reply == NULL) +    { +      if (dbus_connection_get_is_connected (connection)) +        dbus_set_error (error, DBUS_ERROR_NO_REPLY, "Message did not receive a reply"); +      else +        dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Disconnected prior to receiving a reply"); + +      return NULL; +    } +  else if (dbus_set_error_from_message (error, reply)) +    { +      dbus_message_unref (reply); +      return NULL; +    } +  else +    return reply; +} + +/**   * Blocks until the outgoing message queue is empty.   *   * @param connection the connection. @@ -2301,6 +2373,10 @@ dbus_connection_get_dispatch_status (DBusConnection *connection)   * be part of authentication or the like.   *   * @todo some FIXME in here about handling DBUS_HANDLER_RESULT_NEED_MEMORY + * + * @todo right now a message filter gets run on replies to a pending + * call in here, but not in the case where we block without + * entering the main loop.   *    * @param connection the connection   * @returns dispatch status @@ -2435,18 +2511,7 @@ dbus_connection_dispatch (DBusConnection *connection)    if (pending)      { -      _dbus_verbose ("  handing message %p to pending call\n", message); - -      _dbus_assert (pending->reply == NULL); -      pending->reply = message; -      dbus_message_ref (pending->reply); - -      dbus_pending_call_ref (pending); /* in case there's no app with a ref held */ -      _dbus_connection_detach_pending_call_and_unlock (connection, pending); - -      /* Must be called unlocked since it invokes app callback */ -      _dbus_pending_call_notify (pending); -      dbus_pending_call_unref (pending); +      _dbus_pending_call_complete_and_unlock (pending, message);        pending = NULL; @@ -2869,6 +2934,10 @@ dbus_connection_set_unix_user_function (DBusConnection             *connection,   * forgets about it. Thus the caller of this function must keep a   * reference to the message handler.   * + * @todo we don't run filters on messages while blocking without + * entering the main loop, since filters are run as part of + * dbus_connection_dispatch(). + *   * @param connection the connection   * @param handler the handler   * @returns #TRUE on success, #FALSE if not enough memory. diff --git a/dbus/dbus-pending-call.c b/dbus/dbus-pending-call.c index 84ca7ae0..2b6021e9 100644 --- a/dbus/dbus-pending-call.c +++ b/dbus/dbus-pending-call.c @@ -254,6 +254,31 @@ dbus_pending_call_get_reply (DBusPendingCall *pending)    return pending->reply;  } +/** + * Block until the pending call is completed.  The blocking is as with + * dbus_connection_send_with_reply_and_block(); it does not enter the + * main loop or process other messages, it simply waits for the reply + * in question. + * + * @todo when you start blocking, the timeout is reset, but it should + * really only use time remaining since the pending call was created. + * + * @param pending the pending call + */ +void +dbus_pending_call_block (DBusPendingCall *pending) +{ +  DBusMessage *message; +   +  message = _dbus_connection_block_for_reply (pending->connection, +                                              pending->reply_serial, +                                              dbus_timeout_get_interval (pending->timeout)); + +  _dbus_connection_lock (pending->connection); +  _dbus_pending_call_complete_and_unlock (pending, message); +  dbus_message_unref (message); +} +  /** @} */  #ifdef DBUS_BUILD_TESTS diff --git a/dbus/dbus-pending-call.h b/dbus/dbus-pending-call.h index 66f1bac5..81af872f 100644 --- a/dbus/dbus-pending-call.h +++ b/dbus/dbus-pending-call.h @@ -42,6 +42,7 @@ void         dbus_pending_call_set_notify    (DBusPendingCall               *pen  void         dbus_pending_call_cancel        (DBusPendingCall               *pending);  dbus_bool_t  dbus_pending_call_get_completed (DBusPendingCall               *pending);  DBusMessage* dbus_pending_call_get_reply     (DBusPendingCall               *pending); +void         dbus_pending_call_block         (DBusPendingCall               *pending);  DBUS_END_DECLS; diff --git a/glib/dbus-gproxy.h b/glib/dbus-gproxy.h index bebcd1ce..47b70f36 100644 --- a/glib/dbus-gproxy.h +++ b/glib/dbus-gproxy.h @@ -34,43 +34,43 @@  G_BEGIN_DECLS  typedef struct DBusGProxy       DBusGProxy; -typedef struct DBusGPendingCall DBusGPendingCall; +typedef struct DBusPendingCall DBusPendingCall; -DBusGProxy*       dbus_gproxy_new_for_service        (DBusConnection          *connection, -                                                      const char              *service_name, -                                                      const char              *interface_name); -DBusGProxy*       dbus_gproxy_new_for_service_owner  (DBusConnection          *connection, -                                                      const char              *service_name, -                                                      const char              *interface_name, -                                                      GError                 **error); -DBusGProxy*       dbus_gproxy_new_for_object_id      (DBusConnection          *connection, -                                                      const DBusObjectID      *object_id, -                                                      const char              *interface_name); -DBusGProxy*       dbus_gproxy_new_for_interface      (DBusConnection          *connection, -                                                      const char              *interface_name); -void              dbus_gproxy_ref                    (DBusGProxy              *proxy); -void              dbus_gproxy_unref                  (DBusGProxy              *proxy); -gboolean          dbus_gproxy_connect_signal         (DBusGProxy              *proxy, -                                                      const char              *signal_name, -                                                      GCallback                callback, -                                                      void                    *data, -                                                      GFreeFunc                free_data_func, -                                                      GError                 **error); -DBusGPendingCall* dbus_gproxy_begin_call             (DBusGProxy              *proxy, -                                                      const char              *method, -                                                      int                      first_arg_type, -                                                      ...); -void              dbus_gproxy_oneway_call            (DBusGProxy              *proxy, -                                                      const char              *method, -                                                      int                      first_arg_type, -                                                      ...); +DBusGProxy*      dbus_gproxy_new_for_service       (DBusConnection      *connection, +                                                    const char          *service_name, +                                                    const char          *interface_name); +DBusGProxy*      dbus_gproxy_new_for_service_owner (DBusConnection      *connection, +                                                    const char          *service_name, +                                                    const char          *interface_name, +                                                    GError             **error); +DBusGProxy*      dbus_gproxy_new_for_object_id     (DBusConnection      *connection, +                                                    const DBusObjectID  *object_id, +                                                    const char          *interface_name); +DBusGProxy*      dbus_gproxy_new_for_interface     (DBusConnection      *connection, +                                                    const char          *interface_name); +void             dbus_gproxy_ref                   (DBusGProxy          *proxy); +void             dbus_gproxy_unref                 (DBusGProxy          *proxy); +gboolean         dbus_gproxy_connect_signal        (DBusGProxy          *proxy, +                                                    const char          *signal_name, +                                                    GCallback            callback, +                                                    void                *data, +                                                    GFreeFunc            free_data_func, +                                                    GError             **error); +DBusPendingCall* dbus_gproxy_begin_call            (DBusGProxy          *proxy, +                                                    const char          *method, +                                                    int                  first_arg_type, +                                                    ...); +void             dbus_gproxy_oneway_call           (DBusGProxy          *proxy, +                                                    const char          *method, +                                                    int                  first_arg_type, +                                                    ...); +gboolean         dbus_pending_call_is_complete     (DBusPendingCall     *call); +void             dbus_pending_call_cancel_and_free (DBusPendingCall     *call); +gboolean         dbus_pending_call_block_and_free  (DBusPendingCall     *call, +                                                    GError             **error, +                                                    int                  first_arg_type, +                                                    ...); -gboolean          dbus_gpending_call_is_complete     (DBusGPendingCall        *call); -void              dbus_gpending_call_cancel_and_free (DBusGPendingCall        *call); -gboolean          dbus_gpending_call_block_and_free  (DBusGPendingCall        *call, -                                                      GError                 **error, -                                                      int                      first_arg_type, -                                                      ...);  | 
