From c4e3cfbf4070d9bf255d08e23591e8a8dc476d72 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 17 Dec 2007 16:00:33 +0000 Subject: [PATCH] Add is_supported() to GNativeVolumeMonitorClass so that we can avoid 2007-12-17 Alexander Larsson * gnativevolumemonitor.h: * gunionvolumemonitor.c: * gunixvolumemonitor.c: Add is_supported() to GNativeVolumeMonitorClass so that we can avoid having to create an object to see if the backend is supported at runtime. Also add name member and an env var to pick a specific volume monitor backend. * gmountprivate.h: * glocalfile.c: Add cancellable to _g_mount_get_for_mount_path() * glocaldirectorymonitor.c: * glocalfilemonitor.c: Avoid loading and unloading modules while sorting. svn path=/trunk/; revision=6144 --- gio/ChangeLog | 19 ++++++ gio/glocaldirectorymonitor.c | 7 ++ gio/glocalfile.c | 2 +- gio/glocalfilemonitor.c | 7 ++ gio/gmountprivate.h | 3 +- gio/gnativevolumemonitor.h | 7 +- gio/gunionvolumemonitor.c | 125 +++++++++++++++++++---------------- gio/gunixvolumemonitor.c | 11 ++- 8 files changed, 118 insertions(+), 63 deletions(-) diff --git a/gio/ChangeLog b/gio/ChangeLog index 8fd3ac712..13f0ed1aa 100644 --- a/gio/ChangeLog +++ b/gio/ChangeLog @@ -1,3 +1,22 @@ +2007-12-17 Alexander Larsson + + * gnativevolumemonitor.h: + * gunionvolumemonitor.c: + * gunixvolumemonitor.c: + Add is_supported() to GNativeVolumeMonitorClass so + that we can avoid having to create an object to see + if the backend is supported at runtime. + Also add name member and an env var to pick a specific + volume monitor backend. + + * gmountprivate.h: + * glocalfile.c: + Add cancellable to _g_mount_get_for_mount_path() + + * glocaldirectorymonitor.c: + * glocalfilemonitor.c: + Avoid loading and unloading modules while sorting. + 2007-12-17 Matthias Clasen * gio.symbols: diff --git a/gio/glocaldirectorymonitor.c b/gio/glocaldirectorymonitor.c index 5a275ece7..5f8262ff7 100644 --- a/gio/glocaldirectorymonitor.c +++ b/gio/glocaldirectorymonitor.c @@ -237,6 +237,10 @@ get_default_local_directory_monitor (gpointer data) chosen_type = G_TYPE_INVALID; + /* Ref all classes once so we don't load/unload them a lot */ + for (i = 0; i < n_monitor_impls; i++) + g_type_class_ref (monitor_impls[i]); + g_qsort_with_data (monitor_impls, n_monitor_impls, sizeof (GType), @@ -255,6 +259,9 @@ get_default_local_directory_monitor (gpointer data) g_type_class_unref (klass); } + for (i = 0; i < n_monitor_impls; i++) + g_type_class_unref (g_type_class_peek (monitor_impls[i])); + g_free (monitor_impls); *ret = chosen_type; diff --git a/gio/glocalfile.c b/gio/glocalfile.c index 9dcb96226..1140ffeba 100644 --- a/gio/glocalfile.c +++ b/gio/glocalfile.c @@ -898,7 +898,7 @@ g_local_file_find_enclosing_mount (GFile *file, return NULL; } - mount = _g_mount_get_for_mount_path (mountpoint); + mount = _g_mount_get_for_mount_path (mountpoint, cancellable); g_free (mountpoint); if (mount) return mount; diff --git a/gio/glocalfilemonitor.c b/gio/glocalfilemonitor.c index f955894fd..3b6621e74 100644 --- a/gio/glocalfilemonitor.c +++ b/gio/glocalfilemonitor.c @@ -165,6 +165,10 @@ get_default_local_file_monitor (gpointer data) chosen_type = G_TYPE_INVALID; + /* Ref all classes once so we don't load/unload them a lot */ + for (i = 0; i < n_monitor_impls; i++) + g_type_class_ref (monitor_impls[i]); + g_qsort_with_data (monitor_impls, n_monitor_impls, sizeof (GType), @@ -183,6 +187,9 @@ get_default_local_file_monitor (gpointer data) g_type_class_unref (klass); } + for (i = 0; i < n_monitor_impls; i++) + g_type_class_unref (g_type_class_peek (monitor_impls[i])); + g_free (monitor_impls); *ret = chosen_type; diff --git a/gio/gmountprivate.h b/gio/gmountprivate.h index 836613e48..74e9852f0 100644 --- a/gio/gmountprivate.h +++ b/gio/gmountprivate.h @@ -27,7 +27,8 @@ G_BEGIN_DECLS -GMount *_g_mount_get_for_mount_path (const char *mount_path); +GMount *_g_mount_get_for_mount_path (const char *mount_path, + GCancellable *cancellable); G_END_DECLS diff --git a/gio/gnativevolumemonitor.h b/gio/gnativevolumemonitor.h index 0b193ffd9..ac1675522 100644 --- a/gio/gnativevolumemonitor.h +++ b/gio/gnativevolumemonitor.h @@ -22,9 +22,12 @@ struct _GNativeVolumeMonitor { struct _GNativeVolumeMonitorClass { GVolumeMonitorClass parent_class; - GMount * (*get_mount_for_mount_path) (const char *mount_path); - int priority; + char *name; + + GMount * (*get_mount_for_mount_path) (const char *mount_path, + GCancellable *cancellable); + gboolean (*is_supported) (void); }; GType g_native_volume_monitor_get_type (void) G_GNUC_CONST; diff --git a/gio/gunionvolumemonitor.c b/gio/gunionvolumemonitor.c index 92ed3058e..3fb6485a8 100644 --- a/gio/gunionvolumemonitor.c +++ b/gio/gunionvolumemonitor.c @@ -390,16 +390,49 @@ g_union_volume_monitor_remove_monitor (GUnionVolumeMonitor *union_monitor, g_signal_handlers_disconnect_by_func (child_monitor, child_drive_changed, union_monitor); } -static GType -get_default_native_type_with_exclude (GType type_to_exclude) +/* Note: This compares in reverse order. + Higher prio -> sort first + */ +static gint +compare_monitor_type (gconstpointer a, + gconstpointer b, + gpointer user_data) +{ + GNativeVolumeMonitorClass *class_a, *class_b; + gint res; + const char *use_this_monitor; + + /* We ref:ed all the classes, so the peek is safe */ + class_a = g_type_class_peek (*(GType *)a); + class_b = g_type_class_peek (*(GType *)b); + use_this_monitor = user_data; + + if (class_a == class_b) + res = 0; + else if (use_this_monitor != NULL && + strcmp (class_a->name, use_this_monitor) == 0) + res = -1; + else if (use_this_monitor != NULL && + strcmp (class_b->name, use_this_monitor) == 0) + res = 1; + else + res = class_b->priority - class_a->priority; + + return res; +} + +static GTypeClass * +get_default_native_class (gpointer data) { GNativeVolumeMonitorClass *klass; GType *monitors; guint n_monitors; - GType native_type; - int native_prio; + GTypeClass *native_class; + const char *use_this; int i; - + + use_this = g_getenv ("GIO_USE_VOLUME_MONITOR"); + #ifdef G_OS_UNIX /* Ensure GUnixVolumeMonitor type is available */ { @@ -413,55 +446,44 @@ get_default_native_type_with_exclude (GType type_to_exclude) _g_io_modules_ensure_loaded (); monitors = g_type_children (G_TYPE_NATIVE_VOLUME_MONITOR, &n_monitors); - native_type = 0; - native_prio = -1; + + /* Ref all classes once so we don't load/unload them a lot */ + for (i = 0; i < n_monitors; i++) + g_type_class_ref (monitors[i]); + g_qsort_with_data (monitors, n_monitors, sizeof (GType), + compare_monitor_type, (gpointer)use_this); + + native_class = NULL; for (i = 0; i < n_monitors; i++) { - if (monitors[i] != type_to_exclude) - { - klass = G_NATIVE_VOLUME_MONITOR_CLASS (g_type_class_ref (monitors[i])); + klass = G_NATIVE_VOLUME_MONITOR_CLASS (g_type_class_ref (monitors[i])); - if (klass->priority > native_prio) - { - native_prio = klass->priority; - native_type = monitors[i]; - } - - g_type_class_unref (klass); - } + if (klass->is_supported ()) + { + native_class = (GTypeClass *)klass; + break; + } + g_type_class_unref (klass); } - + + for (i = 0; i < n_monitors; i++) + g_type_class_unref (g_type_class_peek (monitors[i])); + g_free (monitors); - return native_type; + return native_class; } -static gpointer -get_default_native_type (gpointer data) -{ - GType *ret = (GType *) data; - - *ret = get_default_native_type_with_exclude (G_TYPE_INVALID); - return NULL; -} - -static GOnce _once_init = G_ONCE_INIT; -static GType _type = G_TYPE_INVALID; static GType get_native_type () { + static GOnce _once_init = G_ONCE_INIT; - g_once (&_once_init, get_default_native_type, &_type); - - return _type; -} + g_once (&_once_init, (GThreadFunc)get_default_native_class, NULL); -static void -update_native_type (GType type) -{ - _type = type; + return G_TYPE_FROM_CLASS (_once_init.retval); } static void @@ -478,22 +500,8 @@ g_union_volume_monitor_init (GUnionVolumeMonitor *union_monitor) if (native_type != G_TYPE_INVALID) { monitor = g_object_new (native_type, NULL); - /* A native file monitor (the hal one if hald isn't running for - * example) may very well fail so handle falling back to the - * native one shipped with gio (e.g. GUnixVolumeMonitor) - */ - if (monitor == NULL) - { - native_type = get_default_native_type_with_exclude (native_type); - monitor = g_object_new (native_type, NULL); - } - - if (monitor != NULL) - { - g_union_volume_monitor_add_monitor (union_monitor, monitor); - g_object_unref (monitor); - update_native_type (native_type); - } + g_union_volume_monitor_add_monitor (union_monitor, monitor); + g_object_unref (monitor); } monitors = g_type_children (G_TYPE_VOLUME_MONITOR, &n_monitors); @@ -522,7 +530,6 @@ g_union_volume_monitor_new (void) return monitor; } - /** * g_volume_monitor_get: * @@ -554,11 +561,13 @@ g_volume_monitor_get (void) /** * _g_mount_get_for_mount_path: * @mountpoint: a string. + * @cancellable: a #GCancellable, or %NULL * * Returns: a #GMount for given @mount_path or %NULL. **/ GMount * -_g_mount_get_for_mount_path (const char *mount_path) +_g_mount_get_for_mount_path (const char *mount_path, + GCancellable *cancellable) { GType native_type; GNativeVolumeMonitorClass *klass; @@ -575,7 +584,7 @@ _g_mount_get_for_mount_path (const char *mount_path) if (klass->get_mount_for_mount_path) { G_LOCK (the_volume_monitor); - mount = klass->get_mount_for_mount_path (mount_path); + mount = klass->get_mount_for_mount_path (mount_path, cancellable); G_UNLOCK (the_volume_monitor); } diff --git a/gio/gunixvolumemonitor.c b/gio/gunixvolumemonitor.c index dab8eca01..dd4b82eaf 100644 --- a/gio/gunixvolumemonitor.c +++ b/gio/gunixvolumemonitor.c @@ -131,8 +131,15 @@ get_mount_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) return NULL; } +static gboolean +is_supported (void) +{ + return TRUE; +} + static GMount * -get_mount_for_mount_path (const char *mount_path) +get_mount_for_mount_path (const char *mount_path, + GCancellable *cancellable) { GUnixMountEntry *mount_entry; GUnixMount *mount; @@ -161,6 +168,8 @@ g_unix_volume_monitor_class_init (GUnixVolumeMonitorClass *klass) monitor_class->get_mount_for_uuid = get_mount_for_uuid; native_class->priority = 0; + native_class->name = "unix"; + native_class->is_supported = is_supported; native_class->get_mount_for_mount_path = get_mount_for_mount_path; }