exported-object: refactor list of interfaces from GSList to an array

NMExportedObject is the center of every D-Bus exported object in
NetworkManager's core. It makes sense to optimize it.

Transform the GSList of interfaces to be a array. The array is still
allocated via the slice allocator (as we expect that there are only few
types in the list). This saves the overhead to allocate a GSList item
for each entry.

Another advantage is that the interfaces list is now strongly typed
instead of an opaque data pointer.
This commit is contained in:
Thomas Haller
2016-03-30 12:28:28 +02:00
parent efae518e3c
commit 6a42e18d53
2 changed files with 66 additions and 44 deletions

View File

@@ -38,13 +38,18 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMExportedObject, nm_exported_object, G_TYPE_D
prefix_counters = g_hash_table_new (g_str_hash, g_str_equal); prefix_counters = g_hash_table_new (g_str_hash, g_str_equal);
) )
typedef struct {
GDBusInterfaceSkeleton *interface;
} InterfaceData;
typedef struct { typedef struct {
NMBusManager *bus_mgr; NMBusManager *bus_mgr;
char *path; char *path;
GHashTable *pending_notifies; GHashTable *pending_notifies;
GSList *interfaces; InterfaceData *interfaces;
guint num_interfaces;
guint notify_idle_id; guint notify_idle_id;
@@ -148,17 +153,18 @@ nm_exported_object_signal_hook (GSignalInvocationHint *ihint,
NMExportedObjectPrivate *priv; NMExportedObjectPrivate *priv;
GSignalQuery *signal_info = data; GSignalQuery *signal_info = data;
GDBusInterfaceSkeleton *interface = NULL; GDBusInterfaceSkeleton *interface = NULL;
GSList *iter;
GValue *dbus_param_values; GValue *dbus_param_values;
int i; guint i;
priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self); priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
if (!priv->path) if (!priv->path)
return TRUE; return TRUE;
for (iter = priv->interfaces; iter; iter = iter->next) { for (i = 0; i < priv->num_interfaces; i++) {
if (g_type_is_a (G_OBJECT_TYPE (iter->data), signal_info->itype)) { InterfaceData *ifdata = &priv->interfaces[i];
interface = G_DBUS_INTERFACE_SKELETON (iter->data);
if (g_type_is_a (G_OBJECT_TYPE (ifdata->interface), signal_info->itype)) {
interface = ifdata->interface;
break; break;
} }
} }
@@ -453,9 +459,10 @@ nm_exported_object_create_skeletons (NMExportedObject *self,
GObjectClass *object_class; GObjectClass *object_class;
NMExportedObjectClassInfo *classinfo; NMExportedObjectClassInfo *classinfo;
GSList *iter; GSList *iter;
GDBusInterfaceSkeleton *interface;
const NMExportedObjectDBusMethodImpl *methods; const NMExportedObjectDBusMethodImpl *methods;
guint methods_len; guint i, methods_len;
guint num_interfaces;
InterfaceData *interfaces;
classinfo = g_type_get_qdata (object_type, nm_exported_object_class_info_quark ()); classinfo = g_type_get_qdata (object_type, nm_exported_object_class_info_quark ());
if (!classinfo) if (!classinfo)
@@ -467,17 +474,30 @@ nm_exported_object_create_skeletons (NMExportedObject *self,
methods = classinfo->methods->len ? &g_array_index (classinfo->methods, NMExportedObjectDBusMethodImpl, 0) : NULL; methods = classinfo->methods->len ? &g_array_index (classinfo->methods, NMExportedObjectDBusMethodImpl, 0) : NULL;
methods_len = classinfo->methods->len; methods_len = classinfo->methods->len;
for (iter = classinfo->skeleton_types; iter; iter = iter->next) { num_interfaces = g_slist_length (classinfo->skeleton_types);
interface = nm_exported_object_skeleton_create (GPOINTER_TO_SIZE (iter->data), g_return_if_fail (num_interfaces > 0);
object_class,
methods,
methods_len,
(GObject *) self);
g_dbus_object_skeleton_add_interface ((GDBusObjectSkeleton *) self, interface); interfaces = g_slice_alloc (sizeof (InterfaceData) * (num_interfaces + priv->num_interfaces));
priv->interfaces = g_slist_prepend (priv->interfaces, interface); for (i = num_interfaces, iter = classinfo->skeleton_types; iter; iter = iter->next) {
InterfaceData *ifdata = &interfaces[--i];
ifdata->interface = nm_exported_object_skeleton_create (GPOINTER_TO_SIZE (iter->data),
object_class,
methods,
methods_len,
(GObject *) self);
g_dbus_object_skeleton_add_interface ((GDBusObjectSkeleton *) self, ifdata->interface);
} }
nm_assert (i == 0);
if (priv->num_interfaces > 0) {
memcpy (&interfaces[num_interfaces], priv->interfaces, sizeof (InterfaceData) * priv->num_interfaces);
g_slice_free1 (sizeof (InterfaceData) * priv->num_interfaces, priv->interfaces);
}
priv->num_interfaces = num_interfaces + priv->num_interfaces;
priv->interfaces = interfaces;
} }
void void
@@ -506,16 +526,22 @@ static void
nm_exported_object_destroy_skeletons (NMExportedObject *self) nm_exported_object_destroy_skeletons (NMExportedObject *self)
{ {
NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self); NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
guint n;
g_return_if_fail (priv->interfaces); g_return_if_fail (priv->num_interfaces > 0);
nm_assert (priv->interfaces);
while (priv->interfaces) { n = priv->num_interfaces;
GDBusInterfaceSkeleton *interface = priv->interfaces->data;
priv->interfaces = g_slist_delete_link (priv->interfaces, priv->interfaces); while (priv->num_interfaces > 0) {
g_dbus_object_skeleton_remove_interface ((GDBusObjectSkeleton *) self, interface); InterfaceData *ifdata = &priv->interfaces[--priv->num_interfaces];
nm_exported_object_skeleton_release (interface);
g_dbus_object_skeleton_remove_interface ((GDBusObjectSkeleton *) self, ifdata->interface);
nm_exported_object_skeleton_release (ifdata->interface);
} }
g_slice_free1 (sizeof (InterfaceData) * n, priv->interfaces);
priv->interfaces = NULL;
} }
/** /**
@@ -664,30 +690,26 @@ nm_exported_object_unexport (NMExportedObject *self)
} }
} }
GSList * GDBusInterfaceSkeleton *
nm_exported_object_get_interfaces (NMExportedObject *self) nm_exported_object_get_interface_by_type (NMExportedObject *self, GType interface_type)
{ {
NMExportedObjectPrivate *priv; NMExportedObjectPrivate *priv;
guint i;
g_return_val_if_fail (NM_IS_EXPORTED_OBJECT (self), NULL); g_return_val_if_fail (NM_IS_EXPORTED_OBJECT (self), NULL);
priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self); priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
g_return_val_if_fail (priv->path, NULL); g_return_val_if_fail (priv->path, NULL);
g_return_val_if_fail (priv->interfaces, NULL); g_return_val_if_fail (priv->num_interfaces > 0, NULL);
return priv->interfaces; nm_assert (priv->interfaces);
}
GDBusInterfaceSkeleton * for (i = 0; i < priv->num_interfaces; i++) {
nm_exported_object_get_interface_by_type (NMExportedObject *self, GType interface_type) InterfaceData *ifdata = &priv->interfaces[i];
{
GSList *interfaces;
interfaces = nm_exported_object_get_interfaces (self); if (G_TYPE_CHECK_INSTANCE_TYPE (ifdata->interface, interface_type))
for (; interfaces; interfaces = interfaces->next) { return ifdata->interface;
if (G_TYPE_CHECK_INSTANCE_TYPE (interfaces->data, interface_type))
return interfaces->data;
} }
return NULL; return NULL;
} }
@@ -742,7 +764,6 @@ idle_emit_properties_changed (gpointer self)
{ {
NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self); NMExportedObjectPrivate *priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self);
gs_unref_variant GVariant *variant = NULL; gs_unref_variant GVariant *variant = NULL;
GSList *iter;
GDBusInterfaceSkeleton *interface = NULL; GDBusInterfaceSkeleton *interface = NULL;
guint signal_id = 0; guint signal_id = 0;
GHashTableIter hash_iter; GHashTableIter hash_iter;
@@ -773,10 +794,12 @@ idle_emit_properties_changed (gpointer self)
g_hash_table_remove_all (priv->pending_notifies); g_hash_table_remove_all (priv->pending_notifies);
for (iter = priv->interfaces; iter; iter = iter->next) { for (i = 0; i < priv->num_interfaces; i++) {
signal_id = g_signal_lookup ("properties-changed", G_OBJECT_TYPE (iter->data)); InterfaceData *ifdata = &priv->interfaces[i];
signal_id = g_signal_lookup ("properties-changed", G_OBJECT_TYPE (ifdata->interface));
if (signal_id != 0) { if (signal_id != 0) {
interface = G_DBUS_INTERFACE_SKELETON (iter->data); interface = ifdata->interface;
break; break;
} }
} }
@@ -819,9 +842,9 @@ nm_exported_object_notify (GObject *object, GParamSpec *pspec)
GValue value = G_VALUE_INIT; GValue value = G_VALUE_INIT;
const GVariantType *vtype; const GVariantType *vtype;
GVariant *variant; GVariant *variant;
GSList *iter; guint i;
if (!priv->interfaces) if (priv->num_interfaces == 0)
return; return;
for (type = G_OBJECT_TYPE (object); type; type = g_type_parent (type)) { for (type = G_OBJECT_TYPE (object); type; type = g_type_parent (type)) {
@@ -843,8 +866,8 @@ nm_exported_object_notify (GObject *object, GParamSpec *pspec)
g_object_get_property (G_OBJECT (object), pspec->name, &value); g_object_get_property (G_OBJECT (object), pspec->name, &value);
vtype = NULL; vtype = NULL;
for (iter = priv->interfaces; iter && !vtype; iter = iter->next) for (i = 0; !vtype && i < priv->num_interfaces; i++)
vtype = find_dbus_property_type (iter->data, dbus_property_name); vtype = find_dbus_property_type (priv->interfaces[i].interface, dbus_property_name);
g_return_if_fail (vtype != NULL); g_return_if_fail (vtype != NULL);
variant = g_dbus_gvalue_to_gvariant (&value, vtype); variant = g_dbus_gvalue_to_gvariant (&value, vtype);

View File

@@ -74,7 +74,6 @@ const char *nm_exported_object_export (NMExportedObject *self);
const char *nm_exported_object_get_path (NMExportedObject *self); const char *nm_exported_object_get_path (NMExportedObject *self);
gboolean nm_exported_object_is_exported (NMExportedObject *self); gboolean nm_exported_object_is_exported (NMExportedObject *self);
void nm_exported_object_unexport (NMExportedObject *self); void nm_exported_object_unexport (NMExportedObject *self);
GSList * nm_exported_object_get_interfaces (NMExportedObject *self);
GDBusInterfaceSkeleton *nm_exported_object_get_interface_by_type (NMExportedObject *self, GType interface_type); GDBusInterfaceSkeleton *nm_exported_object_get_interface_by_type (NMExportedObject *self, GType interface_type);
void _nm_exported_object_clear_and_unexport (NMExportedObject **location); void _nm_exported_object_clear_and_unexport (NMExportedObject **location);