X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgdbusobjectmanagerserver.c;h=bb6f8c23e851a8afbd1f0ea6ec1cf0ffc07084c2;hb=a3d86afa81ff34ce797a3928fd619ead219a37af;hp=7f71b247b2f00968a1bbda3025eb2224546702ca;hpb=1ab29b6c4a2ddf5a60b4cc353422d605197b7696;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gdbusobjectmanagerserver.c b/gio/gdbusobjectmanagerserver.c index 7f71b24..bb6f8c2 100644 --- a/gio/gdbusobjectmanagerserver.c +++ b/gio/gdbusobjectmanagerserver.c @@ -13,9 +13,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Public License along with this library; if not, see . * * Author: David Zeuthen */ @@ -40,8 +38,8 @@ * @include: gio/gio.h * * #GDBusObjectManagerServer is used to export #GDBusObject instances using - * the standardized org.freedesktop.DBus.ObjectManager + * the standardized + * [org.freedesktop.DBus.ObjectManager](http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager) * interface. For example, remote D-Bus clients can get all objects * and properties in a single call. Additionally, any change in the * object hierarchy is broadcast using signals. This means that D-Bus @@ -69,14 +67,19 @@ static void unexport_all (GDBusObjectManagerServer *manager, gboolean only_manag static void g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer *manager, RegistrationData *data, - const gchar *const *interfaces); + const gchar *const *interfaces, + const gchar *object_path); static void g_dbus_object_manager_server_emit_interfaces_removed (GDBusObjectManagerServer *manager, RegistrationData *data, const gchar *const *interfaces); +static gboolean g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer *manager, + const gchar *object_path); + struct _GDBusObjectManagerServerPrivate { + GMutex lock; GDBusConnection *connection; gchar *object_path; gchar *object_path_ending_in_slash; @@ -94,7 +97,8 @@ enum static void dbus_object_manager_interface_init (GDBusObjectManagerIface *iface); G_DEFINE_TYPE_WITH_CODE (GDBusObjectManagerServer, g_dbus_object_manager_server, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT_MANAGER, dbus_object_manager_interface_init)); + G_ADD_PRIVATE (GDBusObjectManagerServer) + G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT_MANAGER, dbus_object_manager_interface_init)) static void g_dbus_object_manager_server_constructed (GObject *object); @@ -112,6 +116,8 @@ g_dbus_object_manager_server_finalize (GObject *object) g_free (manager->priv->object_path); g_free (manager->priv->object_path_ending_in_slash); + g_mutex_clear (&manager->priv->lock); + if (G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->finalize != NULL) G_OBJECT_CLASS (g_dbus_object_manager_server_parent_class)->finalize (object); } @@ -127,7 +133,9 @@ g_dbus_object_manager_server_get_property (GObject *object, switch (prop_id) { case PROP_CONNECTION: + g_mutex_lock (&manager->priv->lock); g_value_set_object (value, manager->priv->connection); + g_mutex_unlock (&manager->priv->lock); break; case PROP_OBJECT_PATH: @@ -211,16 +219,13 @@ g_dbus_object_manager_server_class_init (GDBusObjectManagerServerClass *klass) G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - - g_type_class_add_private (klass, sizeof (GDBusObjectManagerServerPrivate)); } static void g_dbus_object_manager_server_init (GDBusObjectManagerServer *manager) { - manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, - G_TYPE_DBUS_OBJECT_MANAGER_SERVER, - GDBusObjectManagerServerPrivate); + manager->priv = g_dbus_object_manager_server_get_instance_private (manager); + g_mutex_init (&manager->priv->lock); manager->priv->map_object_path_to_data = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, @@ -267,8 +272,13 @@ g_dbus_object_manager_server_set_connection (GDBusObjectManagerServer *manager, g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager)); g_return_if_fail (connection == NULL || G_IS_DBUS_CONNECTION (connection)); + g_mutex_lock (&manager->priv->lock); + if (manager->priv->connection == connection) - goto out; + { + g_mutex_unlock (&manager->priv->lock); + goto out; + } if (manager->priv->connection != NULL) { @@ -281,6 +291,8 @@ g_dbus_object_manager_server_set_connection (GDBusObjectManagerServer *manager, if (manager->priv->connection != NULL) export_all (manager); + g_mutex_unlock (&manager->priv->lock); + g_object_notify (G_OBJECT (manager), "connection"); out: ; @@ -301,21 +313,23 @@ g_dbus_object_manager_server_set_connection (GDBusObjectManagerServer *manager, GDBusConnection * g_dbus_object_manager_server_get_connection (GDBusObjectManagerServer *manager) { + GDBusConnection *ret; g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), NULL); - return manager->priv->connection != NULL ? g_object_ref (manager->priv->connection) : NULL; + g_mutex_lock (&manager->priv->lock); + ret = manager->priv->connection != NULL ? g_object_ref (manager->priv->connection) : NULL; + g_mutex_unlock (&manager->priv->lock); + return ret; } /* ---------------------------------------------------------------------------------------------------- */ static void registration_data_export_interface (RegistrationData *data, - GDBusInterfaceSkeleton *interface_skeleton) + GDBusInterfaceSkeleton *interface_skeleton, + const gchar *object_path) { GDBusInterfaceInfo *info; GError *error; - const gchar *object_path; - - object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object)); info = g_dbus_interface_skeleton_get_info (interface_skeleton); error = NULL; @@ -347,7 +361,7 @@ registration_data_export_interface (RegistrationData *data, /* emit InterfacesAdded on the ObjectManager object */ interfaces[0] = info->name; interfaces[1] = NULL; - g_dbus_object_manager_server_emit_interfaces_added (data->manager, data, interfaces); + g_dbus_object_manager_server_emit_interfaces_added (data->manager, data, interfaces, object_path); } } @@ -386,7 +400,11 @@ on_interface_added (GDBusObject *object, gpointer user_data) { RegistrationData *data = user_data; - registration_data_export_interface (data, G_DBUS_INTERFACE_SKELETON (interface)); + const gchar *object_path; + g_mutex_lock (&data->manager->priv->lock); + object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object)); + registration_data_export_interface (data, G_DBUS_INTERFACE_SKELETON (interface), object_path); + g_mutex_unlock (&data->manager->priv->lock); } static void @@ -395,7 +413,9 @@ on_interface_removed (GDBusObject *object, gpointer user_data) { RegistrationData *data = user_data; + g_mutex_lock (&data->manager->priv->lock); registration_data_unexport_interface (data, G_DBUS_INTERFACE_SKELETON (interface)); + g_mutex_unlock (&data->manager->priv->lock); } /* ---------------------------------------------------------------------------------------------------- */ @@ -425,35 +445,15 @@ registration_data_free (RegistrationData *data) /* ---------------------------------------------------------------------------------------------------- */ -/** - * g_dbus_object_manager_server_export: - * @manager: A #GDBusObjectManagerServer. - * @object: A #GDBusObjectSkeleton. - * - * Exports @object on @manager. - * - * If there is already a #GDBusObject exported at the object path, - * then the old object is removed. - * - * The object path for @object must be in the hierarchy rooted by the - * object path for @manager. - * - * Note that @manager will take a reference on @object for as long as - * it is exported. - * - * Since: 2.30 - */ -void -g_dbus_object_manager_server_export (GDBusObjectManagerServer *manager, - GDBusObjectSkeleton *object) +static void +g_dbus_object_manager_server_export_unlocked (GDBusObjectManagerServer *manager, + GDBusObjectSkeleton *object, + const gchar *object_path) { RegistrationData *data; GList *existing_interfaces; GList *l; GPtrArray *interface_names; - const gchar *object_path; - - object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object)); g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager)); g_return_if_fail (G_IS_DBUS_OBJECT (object)); @@ -463,7 +463,7 @@ g_dbus_object_manager_server_export (GDBusObjectManagerServer *manager, data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path); if (data != NULL) - g_dbus_object_manager_server_unexport (manager, object_path); + g_dbus_object_manager_server_unexport_unlocked (manager, object_path); data = g_new0 (RegistrationData, 1); data->object = g_object_ref (object); @@ -489,17 +489,16 @@ g_dbus_object_manager_server_export (GDBusObjectManagerServer *manager, for (l = existing_interfaces; l != NULL; l = l->next) { GDBusInterfaceSkeleton *interface_skeleton = G_DBUS_INTERFACE_SKELETON (l->data); - registration_data_export_interface (data, interface_skeleton); + registration_data_export_interface (data, interface_skeleton, object_path); g_ptr_array_add (interface_names, g_dbus_interface_skeleton_get_info (interface_skeleton)->name); } - g_list_foreach (existing_interfaces, (GFunc) g_object_unref, NULL); - g_list_free (existing_interfaces); + g_list_free_full (existing_interfaces, g_object_unref); g_ptr_array_add (interface_names, NULL); data->exported = TRUE; /* now emit InterfacesAdded() for all the interfaces */ - g_dbus_object_manager_server_emit_interfaces_added (manager, data, (const gchar *const *) interface_names->pdata); + g_dbus_object_manager_server_emit_interfaces_added (manager, data, (const gchar *const *) interface_names->pdata, object_path); g_ptr_array_unref (interface_names); g_hash_table_insert (manager->priv->map_object_path_to_data, @@ -508,15 +507,43 @@ g_dbus_object_manager_server_export (GDBusObjectManagerServer *manager, } /** + * g_dbus_object_manager_server_export: + * @manager: A #GDBusObjectManagerServer. + * @object: A #GDBusObjectSkeleton. + * + * Exports @object on @manager. + * + * If there is already a #GDBusObject exported at the object path, + * then the old object is removed. + * + * The object path for @object must be in the hierarchy rooted by the + * object path for @manager. + * + * Note that @manager will take a reference on @object for as long as + * it is exported. + * + * Since: 2.30 + */ +void +g_dbus_object_manager_server_export (GDBusObjectManagerServer *manager, + GDBusObjectSkeleton *object) +{ + g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager)); + g_mutex_lock (&manager->priv->lock); + g_dbus_object_manager_server_export_unlocked (manager, object, + g_dbus_object_get_object_path (G_DBUS_OBJECT (object))); + g_mutex_unlock (&manager->priv->lock); +} + +/** * g_dbus_object_manager_server_export_uniquely: * @manager: A #GDBusObjectManagerServer. * @object: An object. * * Like g_dbus_object_manager_server_export() but appends a string of - * the form _N (with N being a natural number) to - * @object's object path if an object with the given path - * already exists. As such, the #GDBusObjectProxy:object-path property - * of @object may be modified. + * the form _N (with N being a natural number) to @object's object path + * if an object with the given path already exists. As such, the + * #GDBusObjectProxy:g-object-path property of @object may be modified. * * Since: 2.30 */ @@ -535,6 +562,8 @@ g_dbus_object_manager_server_export_uniquely (GDBusObjectManagerServer *manager, g_return_if_fail (G_IS_DBUS_OBJECT (object)); g_return_if_fail (g_str_has_prefix (orig_object_path, manager->priv->object_path_ending_in_slash)); + g_mutex_lock (&manager->priv->lock); + object_path = g_strdup (orig_object_path); count = 1; modified = FALSE; @@ -551,33 +580,57 @@ g_dbus_object_manager_server_export_uniquely (GDBusObjectManagerServer *manager, modified = TRUE; } + g_dbus_object_manager_server_export_unlocked (manager, object, object_path); + + g_mutex_unlock (&manager->priv->lock); + if (modified) g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (object), object_path); - g_dbus_object_manager_server_export (manager, object); - g_free (object_path); g_free (orig_object_path); + } /** - * g_dbus_object_manager_server_unexport: + * g_dbus_object_manager_server_is_exported: * @manager: A #GDBusObjectManagerServer. - * @object_path: An object path. - * - * If @manager has an object at @path, removes the object. Otherwise - * does nothing. + * @object: An object. * - * Note that @object_path must be in the hierarchy rooted by the - * object path for @manager. + * Returns whether @object is currently exported on @manager. * - * Returns: %TRUE if object at @object_path was removed, %FALSE otherwise. + * Returns: %TRUE if @object is exported * - * Since: 2.30 - */ + * Since: 2.34 + **/ gboolean -g_dbus_object_manager_server_unexport (GDBusObjectManagerServer *manager, - const gchar *object_path) +g_dbus_object_manager_server_is_exported (GDBusObjectManagerServer *manager, + GDBusObjectSkeleton *object) +{ + RegistrationData *data = NULL; + const gchar *object_path; + gboolean object_is_exported; + + g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE); + g_return_val_if_fail (G_IS_DBUS_OBJECT (object), FALSE); + + g_mutex_lock (&manager->priv->lock); + + object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object)); + if (object_path != NULL) + data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path); + object_is_exported = (data != NULL); + + g_mutex_unlock (&manager->priv->lock); + + return object_is_exported; +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static gboolean +g_dbus_object_manager_server_unexport_unlocked (GDBusObjectManagerServer *manager, + const gchar *object_path) { RegistrationData *data; gboolean ret; @@ -611,6 +664,33 @@ g_dbus_object_manager_server_unexport (GDBusObjectManagerServer *manager, return ret; } +/** + * g_dbus_object_manager_server_unexport: + * @manager: A #GDBusObjectManagerServer. + * @object_path: An object path. + * + * If @manager has an object at @path, removes the object. Otherwise + * does nothing. + * + * Note that @object_path must be in the hierarchy rooted by the + * object path for @manager. + * + * Returns: %TRUE if object at @object_path was removed, %FALSE otherwise. + * + * Since: 2.30 + */ +gboolean +g_dbus_object_manager_server_unexport (GDBusObjectManagerServer *manager, + const gchar *object_path) +{ + gboolean ret; + g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager), FALSE); + g_mutex_lock (&manager->priv->lock); + ret = g_dbus_object_manager_server_unexport_unlocked (manager, object_path); + g_mutex_unlock (&manager->priv->lock); + return ret; +} + /* ---------------------------------------------------------------------------------------------------- */ @@ -745,6 +825,8 @@ manager_method_call (GDBusConnection *connection, GHashTableIter object_iter; RegistrationData *data; + g_mutex_lock (&manager->priv->lock); + if (g_strcmp0 (method_name, "GetManagedObjects") == 0) { g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a{oa{sa{sv}}}")); @@ -760,10 +842,11 @@ manager_method_call (GDBusConnection *connection, g_hash_table_iter_init (&interface_iter, data->map_iface_name_to_iface); while (g_hash_table_iter_next (&interface_iter, NULL, (gpointer) &iface)) { - g_variant_builder_add_value (&interfaces_builder, - g_variant_new ("{s@a{sv}}", - g_dbus_interface_skeleton_get_info (iface)->name, - g_dbus_interface_skeleton_get_properties (iface))); + GVariant *properties = g_dbus_interface_skeleton_get_properties (iface); + g_variant_builder_add (&interfaces_builder, "{s@a{sv}}", + g_dbus_interface_skeleton_get_info (iface)->name, + properties); + g_variant_unref (properties); } iter_object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object)); g_variant_builder_add (&array_builder, @@ -784,6 +867,7 @@ manager_method_call (GDBusConnection *connection, "Unknown method %s - only GetManagedObjects() is supported", method_name); } + g_mutex_unlock (&manager->priv->lock); } static const GDBusInterfaceVTable manager_interface_vtable = @@ -810,12 +894,12 @@ g_dbus_object_manager_server_constructed (GObject *object) static void g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer *manager, RegistrationData *data, - const gchar *const *interfaces) + const gchar *const *interfaces, + const gchar *object_path) { GVariantBuilder array_builder; GError *error; guint n; - const gchar *object_path; if (data->manager->priv->connection == NULL) goto out; @@ -824,16 +908,16 @@ g_dbus_object_manager_server_emit_interfaces_added (GDBusObjectManagerServer *ma for (n = 0; interfaces[n] != NULL; n++) { GDBusInterfaceSkeleton *iface; + GVariant *properties; + iface = g_hash_table_lookup (data->map_iface_name_to_iface, interfaces[n]); g_assert (iface != NULL); - g_variant_builder_add_value (&array_builder, - g_variant_new ("{s@a{sv}}", - interfaces[n], - g_dbus_interface_skeleton_get_properties (iface))); + properties = g_dbus_interface_skeleton_get_properties (iface); + g_variant_builder_add (&array_builder, "{s@a{sv}}", interfaces[n], properties); + g_variant_unref (properties); } error = NULL; - object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (data->object)); g_dbus_connection_emit_signal (data->manager->priv->connection, NULL, /* destination_bus_name */ manager->priv->object_path, @@ -891,6 +975,8 @@ g_dbus_object_manager_server_get_objects (GDBusObjectManager *_manager) GHashTableIter iter; RegistrationData *data; + g_mutex_lock (&manager->priv->lock); + ret = NULL; g_hash_table_iter_init (&iter, manager->priv->map_object_path_to_data); while (g_hash_table_iter_next (&iter, NULL, (gpointer) &data)) @@ -898,6 +984,8 @@ g_dbus_object_manager_server_get_objects (GDBusObjectManager *_manager) ret = g_list_prepend (ret, g_object_ref (data->object)); } + g_mutex_unlock (&manager->priv->lock); + return ret; } @@ -917,9 +1005,13 @@ g_dbus_object_manager_server_get_object (GDBusObjectManager *_manager, RegistrationData *data; ret = NULL; + + g_mutex_lock (&manager->priv->lock); data = g_hash_table_lookup (manager->priv->map_object_path_to_data, object_path); if (data != NULL) ret = g_object_ref (data->object); + g_mutex_unlock (&manager->priv->lock); + return ret; }