[libdazzle] recursive-monitor: add ignore callback
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libdazzle] recursive-monitor: add ignore callback
- Date: Thu, 30 Nov 2017 10:54:46 +0000 (UTC)
commit 59d68cf22d2a5523ceca84c29731228eaebfb470
Author: Christian Hergert <chergert redhat com>
Date: Thu Nov 30 02:54:36 2017 -0800
recursive-monitor: add ignore callback
The ignore callback MUST be thread-safe.
This allows ignoring some portions of the tree so that we don't create
watches for things like build directories or other random data we know
isn't important.
src/files/dzl-recursive-file-monitor.c | 113 ++++++++++++++++++++++++++++++--
src/files/dzl-recursive-file-monitor.h | 13 +++-
2 files changed, 116 insertions(+), 10 deletions(-)
---
diff --git a/src/files/dzl-recursive-file-monitor.c b/src/files/dzl-recursive-file-monitor.c
index cace697..11a4fe5 100644
--- a/src/files/dzl-recursive-file-monitor.c
+++ b/src/files/dzl-recursive-file-monitor.c
@@ -38,16 +38,20 @@
struct _DzlRecursiveFileMonitor
{
- GObject parent_instance;
+ GObject parent_instance;
- GFile *root;
- GCancellable *cancellable;
+ GFile *root;
+ GCancellable *cancellable;
- GMutex monitor_lock;
- GHashTable *monitors_by_file;
- GHashTable *files_by_monitor;
+ GMutex monitor_lock;
+ GHashTable *monitors_by_file;
+ GHashTable *files_by_monitor;
- guint start_handler;
+ DzlRecursiveIgnoreFunc ignore_func;
+ gpointer ignore_func_data;
+ GDestroyNotify ignore_func_data_destroy;
+
+ guint start_handler;
};
enum {
@@ -72,6 +76,16 @@ G_DEFINE_TYPE (DzlRecursiveFileMonitor, dzl_recursive_file_monitor, G_TYPE_OBJEC
static GParamSpec *properties [N_PROPS];
static guint signals [N_SIGNALS];
+static gboolean
+dzl_recursive_file_monitor_ignored (DzlRecursiveFileMonitor *self,
+ GFile *file)
+{
+ g_assert (DZL_IS_RECURSIVE_FILE_MONITOR (self));
+ g_assert (G_IS_FILE (file));
+
+ return self->ignore_func (file, self->ignore_func_data);
+}
+
static void
dzl_recursive_file_monitor_unwatch (DzlRecursiveFileMonitor *self,
GFile *file)
@@ -105,6 +119,9 @@ dzl_recursive_file_monitor_changed (DzlRecursiveFileMonitor *self,
g_assert (!other_file || G_IS_FILE (file));
g_assert (G_IS_FILE_MONITOR (monitor));
+ if (dzl_recursive_file_monitor_ignored (self, file))
+ return;
+
if (event == G_FILE_MONITOR_EVENT_DELETED)
{
g_mutex_lock (&self->monitor_lock);
@@ -203,6 +220,9 @@ dzl_recursive_file_monitor_worker (GTask *task,
child = g_file_get_child (root, g_file_info_get_name (info));
+ if (dzl_recursive_file_monitor_ignored (self, child))
+ continue;
+
if (!dzl_recursive_file_monitor_watch (self, child, cancellable, &error))
break;
}
@@ -252,9 +272,22 @@ dzl_recursive_file_monitor_constructed (GObject *object)
return;
}
+ /*
+ * Defer start to the main loop so that the caller can set
+ * things like the ignore func, but not require us to have
+ * soem annoying start/stop API.
+ */
+
self->start_handler = g_idle_add (dzl_recursive_file_monitor_start, self);
}
+static gboolean
+default_ignore_func (GFile *file,
+ gpointer user_data)
+{
+ return FALSE;
+}
+
static void
dzl_recursive_file_monitor_dispose (GObject *object)
{
@@ -263,6 +296,18 @@ dzl_recursive_file_monitor_dispose (GObject *object)
dzl_clear_source (&self->start_handler);
g_cancellable_cancel (self->cancellable);
+ if (self->ignore_func_data && self->ignore_func_data_destroy)
+ {
+ gpointer data = self->ignore_func_data;
+ GDestroyNotify notify = self->ignore_func_data_destroy;
+
+ self->ignore_func = NULL;
+ self->ignore_func_data = NULL;
+ self->ignore_func_data_destroy = NULL;
+
+ notify (data);
+ }
+
G_OBJECT_CLASS (dzl_recursive_file_monitor_parent_class)->dispose (object);
}
@@ -368,6 +413,7 @@ dzl_recursive_file_monitor_init (DzlRecursiveFileMonitor *self)
(GEqualFunc) g_file_equal,
g_object_unref,
g_object_unref);
+ self->ignore_func = default_ignore_func;
}
DzlRecursiveFileMonitor *
@@ -413,3 +459,56 @@ dzl_recursive_file_monitor_get_root (DzlRecursiveFileMonitor *self)
return self->root;
}
+
+/**
+ * dzl_recursive_file_monitor_set_ignore_func:
+ * @self: a #DzlRecursiveFileMonitor
+ * @ignore_func: (scope async): a thread-safe #DzlRecursiveIgnoreFunc
+ * @ignore_func_data: closure data for @ignore_func
+ * @ignore_func_data_destroy: destroy notify for @ignore_func_data
+ *
+ * Sets a callback function to determine if a #GFile should be ignored
+ * from signal emission.
+ *
+ * @ignore_func may be called from a thread other than the default
+ * main thread, so any function used here MUST be thread-safe.
+ *
+ * Any use of a non-thread-safe callback for @ignore_func is a programmer
+ * error.
+ *
+ * If @ignore_func is %NULL, it is set to the default which does not
+ * ignore any files or directories.
+ *
+ * Since: 3.28
+ */
+void
+dzl_recursive_file_monitor_set_ignore_func (DzlRecursiveFileMonitor *self,
+ DzlRecursiveIgnoreFunc ignore_func,
+ gpointer ignore_func_data,
+ GDestroyNotify ignore_func_data_destroy)
+{
+ g_return_if_fail (DZL_IS_RECURSIVE_FILE_MONITOR (self));
+
+ if (ignore_func == NULL)
+ {
+ ignore_func = default_ignore_func;
+ ignore_func_data = NULL;
+ ignore_func_data_destroy = NULL;
+ }
+
+ if (self->ignore_func_data && self->ignore_func_data_destroy)
+ {
+ gpointer data = self->ignore_func_data;
+ GDestroyNotify notify = self->ignore_func_data_destroy;
+
+ self->ignore_func = NULL;
+ self->ignore_func_data = NULL;
+ self->ignore_func_data_destroy = NULL;
+
+ notify (data);
+ }
+
+ self->ignore_func = ignore_func;
+ self->ignore_func_data = ignore_func_data;
+ self->ignore_func_data_destroy = ignore_func_data_destroy;
+}
diff --git a/src/files/dzl-recursive-file-monitor.h b/src/files/dzl-recursive-file-monitor.h
index 355d082..69eaeb7 100644
--- a/src/files/dzl-recursive-file-monitor.h
+++ b/src/files/dzl-recursive-file-monitor.h
@@ -27,9 +27,16 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (DzlRecursiveFileMonitor, dzl_recursive_file_monitor, DZL, RECURSIVE_FILE_MONITOR,
GObject)
-DzlRecursiveFileMonitor *dzl_recursive_file_monitor_new (GFile *root);
-GFile *dzl_recursive_file_monitor_get_root (DzlRecursiveFileMonitor *self);
-void dzl_recursive_file_monitor_cancel (DzlRecursiveFileMonitor *self);
+typedef gboolean (*DzlRecursiveIgnoreFunc) (GFile *file,
+ gpointer user_data);
+
+DzlRecursiveFileMonitor *dzl_recursive_file_monitor_new (GFile *root);
+GFile *dzl_recursive_file_monitor_get_root (DzlRecursiveFileMonitor *self);
+void dzl_recursive_file_monitor_cancel (DzlRecursiveFileMonitor *self);
+void dzl_recursive_file_monitor_set_ignore_func (DzlRecursiveFileMonitor *self,
+ DzlRecursiveIgnoreFunc ignore_func,
+ gpointer
ignore_func_data,
+ GDestroyNotify
ignore_func_data_destroy);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]