diff options
| author | Havoc Pennington <hp@redhat.com> | 2003-07-09 03:41:00 +0000 | 
|---|---|---|
| committer | Havoc Pennington <hp@redhat.com> | 2003-07-09 03:41:00 +0000 | 
| commit | 824d4a5edfe1fa7222ab5cb49928bf78a675b563 (patch) | |
| tree | 67e3e45df77fc7fa4277507895cf650ce7f61917 | |
| parent | d8abf955f5bff3e83cabd267883039f7a42c98c3 (diff) | |
2003-07-08  Havoc Pennington  <hp@pobox.com>
	* dbus/dbus-object.c: implement some of this
	* dbus/dbus-object-registry.c
	(_dbus_object_registry_add_and_unlock): fill in the object_id out
	param
	(_dbus_object_registry_new): handle OOM
| -rw-r--r-- | ChangeLog | 9 | ||||
| -rw-r--r-- | dbus/dbus-connection.c | 45 | ||||
| -rw-r--r-- | dbus/dbus-connection.h | 13 | ||||
| -rw-r--r-- | dbus/dbus-internals.h | 3 | ||||
| -rw-r--r-- | dbus/dbus-message-handler.c | 2 | ||||
| -rw-r--r-- | dbus/dbus-message.h | 1 | ||||
| -rw-r--r-- | dbus/dbus-object-registry.c | 12 | ||||
| -rw-r--r-- | dbus/dbus-object.c | 324 | ||||
| -rw-r--r-- | dbus/dbus-object.h | 25 | ||||
| -rw-r--r-- | dbus/dbus-test.c | 6 | ||||
| -rw-r--r-- | dbus/dbus-test.h | 1 | ||||
| -rw-r--r-- | dbus/dbus-threads.c | 1 | 
12 files changed, 415 insertions, 27 deletions
@@ -1,5 +1,14 @@  2003-07-08  Havoc Pennington  <hp@pobox.com> +	* dbus/dbus-object.c: implement some of this + +	* dbus/dbus-object-registry.c +	(_dbus_object_registry_add_and_unlock): fill in the object_id out +	param +	(_dbus_object_registry_new): handle OOM + +2003-07-08  Havoc Pennington  <hp@pobox.com> +  	* dbus/dbus-object.h: sketch out an API for registering objects  	with a connection, that allows us to use as little as 24 bytes  	per object and lets application code represent an object in  diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 237c195b..ed29edc9 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -2942,6 +2942,51 @@ dbus_connection_unregister_handler (DBusConnection     *connection,    CONNECTION_UNLOCK (connection);  } +/** + * Registers an object with the connection. This object is assigned an + * object ID, and will be visible under this ID and with the provided + * interfaces to the peer application on the other end of the + * connection. The object instance should be passed in as object_impl; + * the instance can be any datatype, as long as it fits in a void*. + * + * As a side effect of calling this function, the "registered" + * callback in the #DBusObjectVTable will be invoked. + *  + * @param connection the connection to register the instance with + * @param interfaces #NULL-terminated array of interface names the instance supports + * @param vtable virtual table of functions for manipulating the instance + * @param object_impl object instance + * @param object_id if non-#NULL, object ID to initialize with the new object's ID + * @returns #FALSE if not enough memory to register the object instance + */ +dbus_bool_t +dbus_connection_register_object (DBusConnection          *connection, +                                 const char             **interfaces, +                                 const DBusObjectVTable  *vtable, +                                 void                    *object_impl, +                                 DBusObjectID            *object_id) +{ + +  return FALSE; +} + +/** + * Reverses the effects of dbus_connection_register_object(), + * and invokes the "unregistered" callback in the #DBusObjectVTable + * for the given object. The passed-in object ID must be a valid, + * registered object ID or the results are undefined. + * + * @param connection the connection to unregister the object ID from + * @param object_id the object ID to unregister + */ +void +dbus_connection_unregister_object (DBusConnection     *connection, +                                   const DBusObjectID *object_id) +{ +   + +} +  static DBusDataSlotAllocator slot_allocator;  _DBUS_DEFINE_GLOBAL_LOCK (connection_slots); diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index ce57c98d..6c0da920 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -28,12 +28,11 @@  #define DBUS_CONNECTION_H  #include <dbus/dbus-errors.h> -#include <dbus/dbus-message.h>  #include <dbus/dbus-memory.h> +#include <dbus/dbus-object.h>  DBUS_BEGIN_DECLS; -typedef struct DBusConnection DBusConnection;  typedef struct DBusWatch DBusWatch;  typedef struct DBusTimeout DBusTimeout;  typedef struct DBusMessageHandler DBusMessageHandler; @@ -172,7 +171,17 @@ void        dbus_connection_unregister_handler (DBusConnection      *connection,                                                  const char         **messages_to_handle,                                                  int                  n_messages); +/* Objects */ +dbus_bool_t dbus_connection_register_object   (DBusConnection          *connection, +                                               const char             **interfaces, +                                               const DBusObjectVTable  *vtable, +                                               void                    *object_impl, +                                               DBusObjectID            *object_id); +void        dbus_connection_unregister_object (DBusConnection          *connection, +                                               const DBusObjectID      *object_id); + +/* Other */  dbus_bool_t dbus_connection_allocate_data_slot (dbus_int32_t     *slot_p);  void        dbus_connection_free_data_slot     (dbus_int32_t     *slot_p);  dbus_bool_t dbus_connection_set_data           (DBusConnection   *connection, diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h index d84017d7..7acda71a 100644 --- a/dbus/dbus-internals.h +++ b/dbus/dbus-internals.h @@ -232,10 +232,11 @@ _DBUS_DECLARE_GLOBAL_LOCK (server_slots);  _DBUS_DECLARE_GLOBAL_LOCK (message_slots);  _DBUS_DECLARE_GLOBAL_LOCK (atomic);  _DBUS_DECLARE_GLOBAL_LOCK (message_handler); +_DBUS_DECLARE_GLOBAL_LOCK (callback_object);  _DBUS_DECLARE_GLOBAL_LOCK (bus);  _DBUS_DECLARE_GLOBAL_LOCK (shutdown_funcs);  _DBUS_DECLARE_GLOBAL_LOCK (system_users); -#define _DBUS_N_GLOBAL_LOCKS (9) +#define _DBUS_N_GLOBAL_LOCKS (10)  dbus_bool_t _dbus_threads_init_debug (void); diff --git a/dbus/dbus-message-handler.c b/dbus/dbus-message-handler.c index f38e5100..8bb4dd18 100644 --- a/dbus/dbus-message-handler.c +++ b/dbus/dbus-message-handler.c @@ -325,7 +325,7 @@ free_test_data (void *data)  }  /** - * @ingroup DBusMessageInternals + * @ingroup DBusMessageHandlerInternals   * Unit test for DBusMessageHandler.   *   * @returns #TRUE on success. diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h index 9f07565c..bd52bd1a 100644 --- a/dbus/dbus-message.h +++ b/dbus/dbus-message.h @@ -31,6 +31,7 @@  #include <dbus/dbus-types.h>  #include <dbus/dbus-arch-deps.h>  #include <dbus/dbus-memory.h> +#include <dbus/dbus-errors.h>  #include <stdarg.h>  DBUS_BEGIN_DECLS; diff --git a/dbus/dbus-object-registry.c b/dbus/dbus-object-registry.c index 9f7ca3ff..eba2d8fb 100644 --- a/dbus/dbus-object-registry.c +++ b/dbus/dbus-object-registry.c @@ -66,7 +66,9 @@ _dbus_object_registry_new (DBusConnection *connection)    DBusObjectRegistry *registry;    registry = dbus_new0 (DBusObjectRegistry, 1); - +  if (registry == NULL) +    return NULL; +      registry->refcount = 1;    registry->connection = connection; @@ -230,7 +232,9 @@ _dbus_object_registry_add_and_unlock (DBusObjectRegistry      *registry,    registry->entries[i].object_impl = object_impl;    info_from_entry (registry, &info, ®istry->entries[i]); - +  if (object_id) +    *object_id = info.object_id; +      /* Drop lock and invoke application code */    _dbus_connection_unlock (registry->connection); @@ -317,8 +321,8 @@ _dbus_object_registry_free_all_unlocked (DBusObjectRegistry *registry)  dbus_bool_t  _dbus_object_registry_test (void)  { - - +  /* FIXME */ +      return TRUE;  } diff --git a/dbus/dbus-object.c b/dbus/dbus-object.c index fdd33dd4..262f75ca 100644 --- a/dbus/dbus-object.c +++ b/dbus/dbus-object.c @@ -1,10 +1,10 @@  /* -*- mode: C; c-file-style: "gnu" -*- */ -/* dbus-object.c  DBusObject type +/* dbus-object.c  Objects   *   * Copyright (C) 2003  Red Hat Inc.   *   * Licensed under the Academic Free License version 1.2 - *  + *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by   * the Free Software Foundation; either version 2 of the License, or @@ -14,7 +14,7 @@   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   * GNU General Public License for more details. - *  + *   * You should have received a copy of the GNU General Public License   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA @@ -25,3 +25,321 @@  #include "dbus-internals.h"  #include "dbus-object.h" +/** + * @defgroup DBusCallbackObjectInternals DBusCallbackObject implementation details + * @ingroup DBusInternals + * @brief DBusCallbackObject private implementation details. + * + * The guts of DBusCallbackObject and its methods. + * + * @{ + */ + +_DBUS_DEFINE_GLOBAL_LOCK (callback_object); + +/** + * @brief Internals of DBusCallbackObject + * + * Object that can send and receive messages. + */ +struct DBusCallbackObject +{ +  DBusAtomic                refcount;             /**< reference count */ +  DBusObjectMessageFunction function;             /**< callback function */ +  void                     *user_data;            /**< user data for function */ +  DBusFreeFunction          free_user_data;       /**< free the user data */ +}; + +static void +callback_object_registered (DBusObjectInfo *info) +{ +  DBusCallbackObject *callback = info->object_impl; + +  dbus_callback_object_ref (callback); +} + +static void +callback_object_unregistered (DBusObjectInfo *info) +{ +  DBusCallbackObject *callback = info->object_impl; + +  dbus_callback_object_unref (callback); +} + +static void +callback_object_message (DBusObjectInfo *info, +                         DBusMessage    *message) +{ +  DBusCallbackObject *callback = info->object_impl; +   +  if (callback->function) +    (* callback->function) (info, message); +} + +/** @} */ + +/** + * @defgroup DBusObject DBusObjectInfo, DBusObjectVTable, DBusCallbackObject + * @ingroup  DBus + * @brief support for object instances + * + * Behind each DBusConnection are object instances. An object instance + * may be a GObject (using GLib), a QObject (using Qt), a built-in + * object type called DBusCallbackObject, or any other representation + * of an object; it's even permissible to have an object that's simply + * an integer value or a pointer to a struct. + * + * Objects are registered with one or more DBusConnection. Registered + * objects receive an object ID, represented by the DBusObjectID type. + * Object IDs can be passed over a DBusConnection and used by the + * remote application to refer to objects. Remote applications can + * also refer to objects by dynamically locating objects that support + * a particular interface. + * + * To define an object, you simply provide three callbacks: one to be + * called when the object is registered with a new connection, one + * to be called when the object is unregistered, and one to be called + * when the object receives a message from the peer on the other end + * of the DBusConnection. The three callbacks are specified in a + * DBusObjectVTable struct. + * + * The DBusObjectInfo struct is used to pass the object pointer + * (object_impl), connection, and object ID to each of the callbacks + * in the virtual table. This struct should be treated as read-only. + * + * DBusCallbackObject is provided for convenience as a way to + * implement an object quickly by writing only one callback function, + * the callback that processes messages. To use DBusCallbackObject, + * simply create one, then call dbus_connection_register_object() + * passing in the provided DBusObjectVTable + * dbus_callback_object_vtable. This is the simplest possible object; + * it simply contains a function to be called whenever a message is + * received. + * + * The DBusCallbackObject will be strong-referenced by the + * DBusConnection, so may be unreferenced once it's registered, and + * will go away either on unregistration or when the connection is + * freed. + * + * One DBusCallbackObject may be registered with any number of + * DBusConnection. + *  + * @{ + */ + +/** + * @typedef DBusCallbackObject + * + * Opaque data type representing a callback object. + */ + +static const DBusObjectVTable callback_object_vtable = { +  callback_object_registered, +  callback_object_unregistered, +  callback_object_message +}; + +/** + * Virtual table for a DBusCallbackObject, used to register the + * callback object with dbus_connection_register_object(). + */ +const DBusObjectVTable* dbus_callback_object_vtable = &callback_object_vtable; + +/** + * Creates a new callback object. The callback function + * may be #NULL for a no-op callback or a callback to + * be assigned a function later. + * + * Use dbus_connection_register_object() along with + * dbus_callback_object_vtable to register the callback object with + * one or more connections.  Each connection will add a reference to + * the callback object, so once it's registered it may be unreferenced + * with dbus_callback_object_unref(). + * + * @param function function to call to handle a message + * @param user_data data to pass to the function + * @param free_user_data function to call to free the user data + * @returns a new DBusCallbackObject or #NULL if no memory. + */ +DBusCallbackObject* +dbus_callback_object_new (DBusObjectMessageFunction   function, +                          void                       *user_data, +                          DBusFreeFunction            free_user_data) +{ +  DBusCallbackObject *callback; + +  callback = dbus_new0 (DBusCallbackObject, 1); +  if (callback == NULL) +    return NULL; + +  callback->refcount.value = 1; +  callback->function = function; +  callback->user_data = user_data; +  callback->free_user_data = free_user_data; + +  return callback; +} + +/** + * Increments the reference count on a callback object. + * + * @param callback the callback + */ +void +dbus_callback_object_ref (DBusCallbackObject *callback) +{ +  _dbus_return_if_fail (callback != NULL); + +  _dbus_atomic_inc (&callback->refcount); +} + + +/** + * Decrements the reference count on a callback object, + * freeing the callback if the count reaches 0. + * + * @param callback the callback + */ +void +dbus_callback_object_unref (DBusCallbackObject *callback) +{ +  dbus_bool_t last_unref; + +  _dbus_return_if_fail (callback != NULL); + +  last_unref = (_dbus_atomic_dec (&callback->refcount) == 1); + +  if (last_unref) +    { +      if (callback->free_user_data) +        (* callback->free_user_data) (callback->user_data); + +      dbus_free (callback); +    } +} + +/** + * Gets the user data for the callback. + * + * @param callback the callback + * @returns the user data + */ +void* +dbus_callback_object_get_data (DBusCallbackObject *callback) +{ +  void* user_data; + +  _dbus_return_val_if_fail (callback != NULL, NULL); + +  _DBUS_LOCK (callback_object); +  user_data = callback->user_data; +  _DBUS_UNLOCK (callback_object); +  return user_data; +} + + +/** + * Sets the user data for the callback. Frees any previously-existing + * user data with the previous free_user_data function. + * + * @param callback the callback + * @param user_data the user data + * @param free_user_data free function for the data + */ +void +dbus_callback_object_set_data (DBusCallbackObject         *callback, +                               void                       *user_data, +                               DBusFreeFunction            free_user_data) +{ +  DBusFreeFunction old_free_func; +  void *old_user_data; + +  _dbus_return_if_fail (callback != NULL); + +  _DBUS_LOCK (callback_object); +  old_free_func = callback->free_user_data; +  old_user_data = callback->user_data; + +  callback->user_data = user_data; +  callback->free_user_data = free_user_data; +  _DBUS_UNLOCK (callback_object); + +  if (old_free_func) +    (* old_free_func) (old_user_data); +} + +/** + * Sets the function to be used to handle messages to the + * callback object. + * + * @param callback the callback + * @param function the function + */ +void +dbus_callback_object_set_function (DBusCallbackObject         *callback, +                                   DBusObjectMessageFunction   function) +{ +  _dbus_return_if_fail (callback != NULL); + +  _DBUS_LOCK (callback_object); +  callback->function = function; +  _DBUS_UNLOCK (callback_object); +} + + +/** @} */ + +#ifdef DBUS_BUILD_TESTS +#include "dbus-test.h" +#include <stdio.h> + +static void +test_message_function (DBusObjectInfo     *info, +                       DBusMessage        *message) +{ +  /* nothing */ +} + +static void +free_test_data (void *data) +{ +  /* does nothing */ +} + +/** + * @ingroup DBusCallbackObjectInternals + * Unit test for DBusCallbackObject. + * + * @returns #TRUE on success. + */ +dbus_bool_t +_dbus_object_test (void) +{ +  DBusCallbackObject *callback; + +#define TEST_DATA ((void*) 0xcafebabe) +   +  callback = dbus_callback_object_new (test_message_function, +                                       TEST_DATA, +                                       free_test_data); + +  _dbus_assert (callback != NULL); +  _dbus_assert (callback->function == test_message_function); + +  if (dbus_callback_object_get_data (callback) != TEST_DATA) +    _dbus_assert_not_reached ("got wrong data"); + +  dbus_callback_object_set_data (callback, NULL, NULL); +  if (dbus_callback_object_get_data (callback) != NULL) +    _dbus_assert_not_reached ("got wrong data after set"); + +  dbus_callback_object_set_function (callback, NULL); +  _dbus_assert (callback->function == NULL); + +  dbus_callback_object_ref (callback); +  dbus_callback_object_unref (callback); +  dbus_callback_object_unref (callback); + +  return TRUE; +} +#endif /* DBUS_BUILD_TESTS */ diff --git a/dbus/dbus-object.h b/dbus/dbus-object.h index 0c92776d..b05d9c4b 100644 --- a/dbus/dbus-object.h +++ b/dbus/dbus-object.h @@ -1,5 +1,5 @@  /* -*- mode: C; c-file-style: "gnu" -*- */ -/* dbus-object.h  DBusObject type +/* dbus-object.h  Objects   *   * Copyright (C) 2003  Red Hat Inc.   * @@ -29,18 +29,19 @@  #include <dbus/dbus-arch-deps.h>  #include <dbus/dbus-types.h> +#include <dbus/dbus-message.h>  #include <dbus/dbus-objectid.h> -#include <dbus/dbus-connection.h>  DBUS_BEGIN_DECLS; +typedef struct DBusConnection     DBusConnection;  typedef struct DBusObjectVTable   DBusObjectVTable;  typedef struct DBusObjectInfo     DBusObjectInfo;  typedef struct DBusCallbackObject DBusCallbackObject;  struct DBusObjectInfo  { -  void               *object_impl; +  void               *object_impl; /**< Object information */    DBusObjectID        object_id;    DBusConnection     *connection;  }; @@ -57,26 +58,18 @@ struct DBusObjectVTable    DBusObjectMessageFunction      message;  }; -dbus_bool_t dbus_connection_register_object   (DBusConnection          *connection, -                                               const char             **interfaces, -                                               const DBusObjectVTable  *vtable, -                                               void                    *object_impl, -                                               DBusObjectID            *object_id); -void        dbus_connection_unregister_object (DBusConnection          *connection, -                                               const DBusObjectID      *object_id); -  extern const DBusObjectVTable *dbus_callback_object_vtable;  DBusCallbackObject* dbus_callback_object_new          (DBusObjectMessageFunction   function,                                                         void                       *user_data,                                                         DBusFreeFunction            free_user_data); -void                dbus_callback_object_ref          (DBusCallbackObject         *handler); -void                dbus_callback_object_unref        (DBusCallbackObject         *handler); -void*               dbus_callback_object_get_data     (DBusCallbackObject         *handler); -void                dbus_callback_object_set_data     (DBusCallbackObject         *handler, +void                dbus_callback_object_ref          (DBusCallbackObject         *callback); +void                dbus_callback_object_unref        (DBusCallbackObject         *callback); +void*               dbus_callback_object_get_data     (DBusCallbackObject         *callback); +void                dbus_callback_object_set_data     (DBusCallbackObject         *callback,                                                         void                       *data,                                                         DBusFreeFunction            free_user_data); -void                dbus_callback_object_set_function (DBusCallbackObject         *handler, +void                dbus_callback_object_set_function (DBusCallbackObject         *callback,                                                         DBusObjectMessageFunction   function); diff --git a/dbus/dbus-test.c b/dbus/dbus-test.c index 220961c7..c3b31107 100644 --- a/dbus/dbus-test.c +++ b/dbus/dbus-test.c @@ -111,6 +111,12 @@ dbus_internal_do_not_use_run_tests (const char *test_data_dir)      die ("object registry");    check_memleaks (); + +  printf ("%s: running object tests\n", "dbus-test"); +  if (!_dbus_object_test ()) +    die ("object"); +   +  check_memleaks ();    printf ("%s: running marshalling tests\n", "dbus-test");    if (!_dbus_marshal_test ()) diff --git a/dbus/dbus-test.h b/dbus/dbus-test.h index c9555e2d..8537be40 100644 --- a/dbus/dbus-test.h +++ b/dbus/dbus-test.h @@ -53,6 +53,7 @@ dbus_bool_t _dbus_sysdeps_test         (void);  dbus_bool_t _dbus_spawn_test           (const char *test_data_dir);  dbus_bool_t _dbus_userdb_test          (const char *test_data_dir);  dbus_bool_t _dbus_memory_test	       (void); +dbus_bool_t _dbus_object_test          (void);  dbus_bool_t _dbus_object_id_test       (void);  dbus_bool_t _dbus_object_registry_test (void); diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c index b604a397..81c3fbfe 100644 --- a/dbus/dbus-threads.c +++ b/dbus/dbus-threads.c @@ -227,6 +227,7 @@ init_global_locks (void)      LOCK_ADDR (message_slots),      LOCK_ADDR (atomic),      LOCK_ADDR (message_handler), +    LOCK_ADDR (callback_object),      LOCK_ADDR (bus),      LOCK_ADDR (shutdown_funcs),      LOCK_ADDR (system_users)  | 
