summaryrefslogtreecommitdiffstats
path: root/dbus
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-07-08 05:07:32 +0000
committerHavoc Pennington <hp@redhat.com>2003-07-08 05:07:32 +0000
commitd8abf955f5bff3e83cabd267883039f7a42c98c3 (patch)
tree8c3f33fcb6fac2593f44bf5cf8cd48f7a46dce1f /dbus
parent3f1ad214b5e5c63697ee208d459b304a4ef6e79b (diff)
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 any conceivable way. * dbus/dbus-object-registry.c: implement the hard bits of the DBusConnection aspect of object API. Not yet wired up.
Diffstat (limited to 'dbus')
-rw-r--r--dbus/Makefile.am4
-rw-r--r--dbus/dbus-connection-internal.h1
-rw-r--r--dbus/dbus-connection.c16
-rw-r--r--dbus/dbus-connection.h1
-rw-r--r--dbus/dbus-object-registry.c325
-rw-r--r--dbus/dbus-object-registry.h50
-rw-r--r--dbus/dbus-object.c27
-rw-r--r--dbus/dbus-object.h85
-rw-r--r--dbus/dbus-objectid.h4
-rw-r--r--dbus/dbus-test.c6
-rw-r--r--dbus/dbus-test.h1
-rw-r--r--dbus/dbus.h1
12 files changed, 521 insertions, 0 deletions
diff --git a/dbus/Makefile.am b/dbus/Makefile.am
index 3c3c14e7..8c919f31 100644
--- a/dbus/Makefile.am
+++ b/dbus/Makefile.am
@@ -17,6 +17,7 @@ dbusinclude_HEADERS= \
dbus-memory.h \
dbus-message.h \
dbus-message-handler.h \
+ dbus-object.h \
dbus-objectid.h \
dbus-protocol.h \
dbus-server.h \
@@ -43,7 +44,10 @@ DBUS_LIB_SOURCES= \
dbus-message.c \
dbus-message-handler.c \
dbus-message-internal.h \
+ dbus-object.c \
dbus-objectid.c \
+ dbus-object-registry.c \
+ dbus-object-registry.h \
dbus-resources.c \
dbus-resources.h \
dbus-server.c \
diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h
index 5ddc0e0a..eaa35955 100644
--- a/dbus/dbus-connection-internal.h
+++ b/dbus/dbus-connection-internal.h
@@ -81,6 +81,7 @@ void _dbus_message_handler_remove_connection (DBusMessageHandl
DBusHandlerResult _dbus_message_handler_handle_message (DBusMessageHandler *handler,
DBusConnection *connection,
DBusMessage *message);
+dbus_uint32_t _dbus_connection_get_id (DBusConnection *connection);
DBUS_END_DECLS;
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index 01b2a7bf..237c195b 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -920,6 +920,22 @@ _dbus_connection_handle_watch (DBusWatch *watch,
return retval;
}
+/**
+ * Get the ID to be used in the high bits of an object ID for an object
+ * registered with this connection.
+ *
+ * @todo implement this function
+ *
+ * @param connection the connection.
+ * @returns the connection portion of the object ID
+ */
+dbus_uint32_t
+_dbus_connection_get_id (DBusConnection *connection)
+{
+ /* FIXME */
+ return 1492;
+}
+
/** @} */
/**
diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h
index 9f4dd7ae..ce57c98d 100644
--- a/dbus/dbus-connection.h
+++ b/dbus/dbus-connection.h
@@ -37,6 +37,7 @@ typedef struct DBusConnection DBusConnection;
typedef struct DBusWatch DBusWatch;
typedef struct DBusTimeout DBusTimeout;
typedef struct DBusMessageHandler DBusMessageHandler;
+typedef struct DBusObject DBusObject;
typedef struct DBusPreallocatedSend DBusPreallocatedSend;
typedef enum
diff --git a/dbus/dbus-object-registry.c b/dbus/dbus-object-registry.c
new file mode 100644
index 00000000..9f7ca3ff
--- /dev/null
+++ b/dbus/dbus-object-registry.c
@@ -0,0 +1,325 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-object-registry.c DBusObjectRegistry (internals of DBusConnection)
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * 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
+ *
+ */
+#include "dbus-object-registry.h"
+#include "dbus-connection-internal.h"
+#include "dbus-internals.h"
+#include <string.h>
+
+/**
+ * @defgroup DBusObjectRegistry Map object IDs to implementations
+ * @ingroup DBusInternals
+ * @brief DBusObjectRegistry is used by DBusConnection to track object IDs
+ *
+ * Types and functions related to DBusObjectRegistry
+ *
+ * @{
+ */
+
+typedef struct DBusObjectEntry DBusObjectEntry;
+
+ /* 14 bits for object index, 32K objects */
+#define DBUS_OBJECT_INDEX_BITS (14)
+#define DBUS_OBJECT_INDEX_MASK (0x7fff)
+#define DBUS_MAX_OBJECTS_PER_CONNECTION DBUS_OBJECT_INDEX_MASK
+struct DBusObjectEntry
+{
+ unsigned int id_index : 14; /**< Index of this entry in the entries array */
+ unsigned int id_times_used : 18; /**< Count of times entry has been used; avoids recycling IDs too often */
+
+ void *object_impl; /**< Pointer to application-supplied implementation */
+ const DBusObjectVTable *vtable; /**< Virtual table for this object */
+};
+
+struct DBusObjectRegistry
+{
+ int refcount;
+ DBusConnection *connection;
+
+ DBusObjectEntry *entries;
+ int n_entries_allocated;
+ int n_entries_used;
+};
+
+DBusObjectRegistry*
+_dbus_object_registry_new (DBusConnection *connection)
+{
+ DBusObjectRegistry *registry;
+
+ registry = dbus_new0 (DBusObjectRegistry, 1);
+
+ registry->refcount = 1;
+ registry->connection = connection;
+
+ return registry;
+}
+
+void
+_dbus_object_registry_ref (DBusObjectRegistry *registry)
+{
+ _dbus_assert (registry->refcount > 0);
+
+ registry->refcount += 1;
+}
+
+void
+_dbus_object_registry_unref (DBusObjectRegistry *registry)
+{
+ _dbus_assert (registry->refcount > 0);
+
+ registry->refcount -= 1;
+
+ if (registry->refcount == 0)
+ {
+ _dbus_assert (registry->n_entries_used == 0);
+
+ dbus_free (registry->entries);
+ dbus_free (registry);
+ }
+}
+
+#define ENTRY_TO_ID(entry) \
+ (((dbus_uint32_t) (entry)->id_index) | \
+ (((dbus_uint32_t)(entry)->id_times_used) << DBUS_OBJECT_INDEX_BITS))
+
+#define ID_TO_INDEX(id) \
+ (((dbus_uint32_t) (id)) | DBUS_OBJECT_INDEX_MASK)
+
+#define ID_TO_TIMES_USED(id) \
+ (((dbus_uint32_t) (id)) >> DBUS_OBJECT_INDEX_BITS)
+
+static DBusObjectEntry*
+validate_id (DBusObjectRegistry *registry,
+ const DBusObjectID *object_id)
+{
+ int idx;
+ int times_used;
+ dbus_uint32_t low_bits;
+
+ low_bits = dbus_object_id_get_low_bits (object_id);
+
+ idx = ID_TO_INDEX (low_bits);
+ times_used = ID_TO_TIMES_USED (low_bits);
+
+ if (idx >= registry->n_entries_allocated)
+ return NULL;
+ if (registry->entries[idx].vtable == NULL)
+ return NULL;
+ if (registry->entries[idx].id_times_used != times_used)
+ return NULL;
+ _dbus_assert (registry->entries[idx].id_index == idx);
+ _dbus_assert (registry->n_entries_used > 0);
+
+ return &registry->entries[idx];
+}
+
+static void
+info_from_entry (DBusObjectRegistry *registry,
+ DBusObjectInfo *info,
+ DBusObjectEntry *entry)
+{
+ info->connection = registry->connection;
+ info->object_impl = entry->object_impl;
+ dbus_object_id_set_high_bits (&info->object_id,
+ _dbus_connection_get_id (registry->connection));
+ dbus_object_id_set_low_bits (&info->object_id,
+ ENTRY_TO_ID (entry));
+}
+
+dbus_bool_t
+_dbus_object_registry_add_and_unlock (DBusObjectRegistry *registry,
+ const char **interfaces,
+ const DBusObjectVTable *vtable,
+ void *object_impl,
+ DBusObjectID *object_id)
+{
+ int i;
+ DBusObjectInfo info;
+
+ if (registry->n_entries_used == registry->n_entries_allocated)
+ {
+ DBusObjectEntry *new_entries;
+ int new_alloc;
+
+ if (registry->n_entries_allocated == 0)
+ new_alloc = 16;
+ else
+ {
+ if (registry->n_entries_allocated == DBUS_MAX_OBJECTS_PER_CONNECTION)
+ {
+ _dbus_warn ("Attempting to register a new D-BUS object, but maximum object count of %d reached\n",
+ DBUS_MAX_OBJECTS_PER_CONNECTION);
+ return FALSE;
+ }
+
+ new_alloc = registry->n_entries_allocated * 2;
+ if (new_alloc > DBUS_MAX_OBJECTS_PER_CONNECTION)
+ new_alloc = DBUS_MAX_OBJECTS_PER_CONNECTION;
+ }
+
+ new_entries = dbus_realloc (registry->entries,
+ new_alloc * sizeof (DBusObjectEntry));
+
+ if (new_entries == NULL)
+ return FALSE;
+
+ memset (&new_entries[registry->n_entries_allocated],
+ '\0',
+ sizeof (DBusObjectEntry) * (new_alloc - registry->n_entries_allocated));
+
+ registry->entries = new_entries;
+ registry->n_entries_allocated = new_alloc;
+ }
+ _dbus_assert (registry->n_entries_used < registry->n_entries_allocated);
+
+ /* We linear search for an available entry. However, short-circuit
+ * the hopefully-common situation where we don't have a sparse
+ * array.
+ */
+ if (registry->entries[registry->n_entries_used].vtable == NULL)
+ {
+ i = registry->n_entries_used;
+ }
+ else
+ {
+ /* If we do have a sparse array, we try to get rid of it rather
+ * than using empty slots on the end, so we won't hit this case
+ * next time.
+ */
+
+ /* If index n_entries_used is occupied, then
+ * there is at least one entry outside of
+ * the range [0, n_entries_used). Thus, there is
+ * at least one blank entry inside that range.
+ */
+ i = 0;
+ while (i < registry->n_entries_used)
+ {
+ if (registry->entries[i].vtable == NULL)
+ break;
+ ++i;
+ }
+
+ _dbus_assert (i < registry->n_entries_used);
+ }
+
+ registry->entries[i].id_index = i;
+ /* Overflow is OK here */
+ registry->entries[i].id_times_used += 1;
+
+ registry->entries[i].vtable = vtable;
+ registry->entries[i].object_impl = object_impl;
+
+ info_from_entry (registry, &info, &registry->entries[i]);
+
+ /* Drop lock and invoke application code */
+ _dbus_connection_unlock (registry->connection);
+
+ (* vtable->registered) (&info);
+
+ return TRUE;
+}
+
+void
+_dbus_object_registry_remove_and_unlock (DBusObjectRegistry *registry,
+ const DBusObjectID *object_id)
+{
+ DBusObjectInfo info;
+ DBusObjectEntry *entry;
+ const DBusObjectVTable *vtable;
+
+ entry = validate_id (registry, object_id);
+ if (entry == NULL)
+ {
+ _dbus_warn ("Tried to unregister a nonexistent D-BUS object ID\n");
+ return;
+ }
+
+ info_from_entry (registry, &info, entry);
+ vtable = entry->vtable;
+ entry->vtable = NULL;
+ entry->object_impl = NULL;
+ registry->n_entries_used -= 1;
+
+ /* Drop lock and invoke application code */
+ _dbus_connection_unlock (registry->connection);
+
+ (* vtable->unregistered) (&info);
+}
+
+void
+_dbus_object_registry_handle_and_unlock (DBusObjectRegistry *registry,
+ DBusMessage *message)
+{
+ /* FIXME */
+}
+
+void
+_dbus_object_registry_free_all_unlocked (DBusObjectRegistry *registry)
+{
+ int i;
+
+ i = 0;
+ while (registry->n_entries_used > 0)
+ {
+ _dbus_assert (i < registry->n_entries_allocated);
+ if (registry->entries[i].vtable != NULL)
+ {
+ DBusObjectInfo info;
+ const DBusObjectVTable *vtable;
+
+ info_from_entry (registry, &info, &registry->entries[i]);
+ vtable = registry->entries[i].vtable;
+ registry->entries[i].vtable = NULL;
+ registry->entries[i].object_impl = NULL;
+ registry->n_entries_used -= 1;
+ _dbus_assert (registry->n_entries_used >= 0);
+
+ (* vtable->unregistered) (&info);
+ }
+
+ ++i;
+ }
+
+ _dbus_assert (registry->n_entries_used == 0);
+}
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include <stdio.h>
+
+/**
+ * @ingroup DBusObjectRegistry
+ * Unit test for DBusObjectRegistry
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_object_registry_test (void)
+{
+
+
+ return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus-object-registry.h b/dbus/dbus-object-registry.h
new file mode 100644
index 00000000..d33664e5
--- /dev/null
+++ b/dbus/dbus-object-registry.h
@@ -0,0 +1,50 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-object-registry.h DBusObjectRegistry (internals of DBusConnection)
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * 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
+ *
+ */
+#ifndef DBUS_OBJECT_REGISTRY_H
+#define DBUS_OBJECT_REGISTRY_H
+
+#include <dbus/dbus-object.h>
+
+DBUS_BEGIN_DECLS;
+
+typedef struct DBusObjectRegistry DBusObjectRegistry;
+
+DBusObjectRegistry* _dbus_object_registry_new (DBusConnection *connection);
+void _dbus_object_registry_ref (DBusObjectRegistry *registry);
+void _dbus_object_registry_unref (DBusObjectRegistry *registry);
+
+dbus_bool_t _dbus_object_registry_add_and_unlock (DBusObjectRegistry *registry,
+ const char **interfaces,
+ const DBusObjectVTable *vtable,
+ void *object_impl,
+ DBusObjectID *object_id);
+void _dbus_object_registry_remove_and_unlock (DBusObjectRegistry *registry,
+ const DBusObjectID *object_id);
+void _dbus_object_registry_handle_and_unlock (DBusObjectRegistry *registry,
+ DBusMessage *message);
+void _dbus_object_registry_free_all_unlocked (DBusObjectRegistry *registry);
+
+
+DBUS_END_DECLS;
+
+#endif /* DBUS_OBJECT_REGISTRY_H */
diff --git a/dbus/dbus-object.c b/dbus/dbus-object.c
new file mode 100644
index 00000000..fdd33dd4
--- /dev/null
+++ b/dbus/dbus-object.c
@@ -0,0 +1,27 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-object.c DBusObject type
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * 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
+ *
+ */
+
+#include <config.h>
+#include "dbus-internals.h"
+#include "dbus-object.h"
+
diff --git a/dbus/dbus-object.h b/dbus/dbus-object.h
new file mode 100644
index 00000000..0c92776d
--- /dev/null
+++ b/dbus/dbus-object.h
@@ -0,0 +1,85 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-object.h DBusObject type
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * 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
+ *
+ */
+#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
+#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef DBUS_OBJECT_H
+#define DBUS_OBJECT_H
+
+#include <dbus/dbus-arch-deps.h>
+#include <dbus/dbus-types.h>
+#include <dbus/dbus-objectid.h>
+#include <dbus/dbus-connection.h>
+
+DBUS_BEGIN_DECLS;
+
+typedef struct DBusObjectVTable DBusObjectVTable;
+typedef struct DBusObjectInfo DBusObjectInfo;
+typedef struct DBusCallbackObject DBusCallbackObject;
+
+struct DBusObjectInfo
+{
+ void *object_impl;
+ DBusObjectID object_id;
+ DBusConnection *connection;
+};
+
+typedef void (* DBusObjectRegisteredFunction) (DBusObjectInfo *info);
+typedef void (* DBusObjectUnregisteredFunction) (DBusObjectInfo *info);
+typedef void (* DBusObjectMessageFunction) (DBusObjectInfo *info,
+ DBusMessage *message);
+
+struct DBusObjectVTable
+{
+ DBusObjectRegisteredFunction registered;
+ DBusObjectUnregisteredFunction unregistered;
+ 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 *data,
+ DBusFreeFunction free_user_data);
+void dbus_callback_object_set_function (DBusCallbackObject *handler,
+ DBusObjectMessageFunction function);
+
+
+DBUS_END_DECLS;
+
+#endif /* DBUS_OBJECT_H */
diff --git a/dbus/dbus-objectid.h b/dbus/dbus-objectid.h
index 57346910..b5e1f606 100644
--- a/dbus/dbus-objectid.h
+++ b/dbus/dbus-objectid.h
@@ -30,6 +30,8 @@
#include <dbus/dbus-arch-deps.h>
#include <dbus/dbus-types.h>
+DBUS_BEGIN_DECLS;
+
typedef struct DBusObjectID DBusObjectID;
struct DBusObjectID
@@ -58,4 +60,6 @@ void dbus_object_id_set_as_integer (DBusObjectID *obj_id
dbus_uint64_t value);
#endif
+DBUS_END_DECLS;
+
#endif /* DBUS_OBJECTID_H */
diff --git a/dbus/dbus-test.c b/dbus/dbus-test.c
index 3d5d14bb..220961c7 100644
--- a/dbus/dbus-test.c
+++ b/dbus/dbus-test.c
@@ -105,6 +105,12 @@ dbus_internal_do_not_use_run_tests (const char *test_data_dir)
die ("object ID");
check_memleaks ();
+
+ printf ("%s: running object registry tests\n", "dbus-test");
+ if (!_dbus_object_registry_test ())
+ die ("object registry");
+
+ 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 512cb9a6..c9555e2d 100644
--- a/dbus/dbus-test.h
+++ b/dbus/dbus-test.h
@@ -54,6 +54,7 @@ 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_id_test (void);
+dbus_bool_t _dbus_object_registry_test (void);
void dbus_internal_do_not_use_run_tests (const char *test_data_dir);
diff --git a/dbus/dbus.h b/dbus/dbus.h
index 38db4f5b..d83a4a50 100644
--- a/dbus/dbus.h
+++ b/dbus/dbus.h
@@ -38,6 +38,7 @@
#include <dbus/dbus-macros.h>
#include <dbus/dbus-message.h>
#include <dbus/dbus-message-handler.h>
+#include <dbus/dbus-object.h>
#include <dbus/dbus-objectid.h>
#include <dbus/dbus-protocol.h>
#include <dbus/dbus-server.h>