mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 23:46:17 +01:00
Bug 575708 - runaway inotify madness ...
2009-03-17 Colin Walters <walters@redhat.com> Bug 575708 - runaway inotify madness ... * gfilemonitor.c: Queue up events in a local list and fire one idle, instead of queuing lots of individual idles which has bad performance behavior. svn path=/trunk/; revision=8010
This commit is contained in:
parent
044733e2a0
commit
1d1fba442f
@ -1,3 +1,11 @@
|
|||||||
|
2009-03-17 Colin Walters <walters@redhat.com>
|
||||||
|
|
||||||
|
Bug 575708 - runaway inotify madness ...
|
||||||
|
|
||||||
|
* gfilemonitor.c: Queue up events in a local list and
|
||||||
|
fire one idle, instead of queuing lots of individual
|
||||||
|
idles which has bad performance behavior.
|
||||||
|
|
||||||
2009-03-17 Alexander Larsson <alexl@redhat.com>
|
2009-03-17 Alexander Larsson <alexl@redhat.com>
|
||||||
|
|
||||||
* glocalfileinputstream.c:
|
* glocalfileinputstream.c:
|
||||||
|
@ -32,6 +32,10 @@
|
|||||||
|
|
||||||
#include "gioalias.h"
|
#include "gioalias.h"
|
||||||
|
|
||||||
|
struct _FileChange;
|
||||||
|
typedef struct _FileChange FileChange;
|
||||||
|
static void file_change_free (FileChange *change);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:gfilemonitor
|
* SECTION:gfilemonitor
|
||||||
* @short_description: File Monitor
|
* @short_description: File Monitor
|
||||||
@ -73,6 +77,9 @@ struct _GFileMonitorPrivate {
|
|||||||
/* Rate limiting change events */
|
/* Rate limiting change events */
|
||||||
GHashTable *rate_limiter;
|
GHashTable *rate_limiter;
|
||||||
|
|
||||||
|
guint pending_file_change_id;
|
||||||
|
GSList *pending_file_changes; /* FileChange */
|
||||||
|
|
||||||
GSource *timeout;
|
GSource *timeout;
|
||||||
guint32 timeout_fires_at;
|
guint32 timeout_fires_at;
|
||||||
};
|
};
|
||||||
@ -169,8 +176,19 @@ static void
|
|||||||
g_file_monitor_dispose (GObject *object)
|
g_file_monitor_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
GFileMonitor *monitor;
|
GFileMonitor *monitor;
|
||||||
|
GFileMonitorPrivate *priv;
|
||||||
|
|
||||||
monitor = G_FILE_MONITOR (object);
|
monitor = G_FILE_MONITOR (object);
|
||||||
|
priv = monitor->priv;
|
||||||
|
|
||||||
|
if (priv->pending_file_change_id)
|
||||||
|
{
|
||||||
|
g_source_remove (priv->pending_file_change_id);
|
||||||
|
priv->pending_file_change_id = 0;
|
||||||
|
}
|
||||||
|
g_slist_foreach (priv->pending_file_changes, (GFunc) file_change_free, NULL);
|
||||||
|
g_slist_free (priv->pending_file_changes);
|
||||||
|
priv->pending_file_changes = NULL;
|
||||||
|
|
||||||
/* Make sure we cancel on last unref */
|
/* Make sure we cancel on last unref */
|
||||||
g_file_monitor_cancel (monitor);
|
g_file_monitor_cancel (monitor);
|
||||||
@ -320,26 +338,15 @@ g_file_monitor_set_rate_limit (GFileMonitor *monitor,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
struct _FileChange {
|
||||||
GFileMonitor *monitor;
|
|
||||||
GFile *child;
|
GFile *child;
|
||||||
GFile *other_file;
|
GFile *other_file;
|
||||||
GFileMonitorEvent event_type;
|
GFileMonitorEvent event_type;
|
||||||
} FileChange;
|
};
|
||||||
|
|
||||||
static gboolean
|
|
||||||
emit_cb (gpointer data)
|
|
||||||
{
|
|
||||||
FileChange *change = data;
|
|
||||||
g_signal_emit (change->monitor, signals[CHANGED], 0,
|
|
||||||
change->child, change->other_file, change->event_type);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
file_change_free (FileChange *change)
|
file_change_free (FileChange *change)
|
||||||
{
|
{
|
||||||
g_object_unref (change->monitor);
|
|
||||||
g_object_unref (change->child);
|
g_object_unref (change->child);
|
||||||
if (change->other_file)
|
if (change->other_file)
|
||||||
g_object_unref (change->other_file);
|
g_object_unref (change->other_file);
|
||||||
@ -347,6 +354,27 @@ file_change_free (FileChange *change)
|
|||||||
g_slice_free (FileChange, change);
|
g_slice_free (FileChange, change);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
emit_cb (gpointer data)
|
||||||
|
{
|
||||||
|
GFileMonitor *monitor = G_FILE_MONITOR (data);
|
||||||
|
GSList *pending, *iter;
|
||||||
|
|
||||||
|
pending = g_slist_reverse (monitor->priv->pending_file_changes);
|
||||||
|
monitor->priv->pending_file_changes = NULL;
|
||||||
|
monitor->priv->pending_file_change_id = 0;
|
||||||
|
|
||||||
|
for (iter = pending; iter; iter = iter->next)
|
||||||
|
{
|
||||||
|
FileChange *change = iter->data;
|
||||||
|
g_signal_emit (monitor, signals[CHANGED], 0,
|
||||||
|
change->child, change->other_file, change->event_type);
|
||||||
|
file_change_free (change);
|
||||||
|
}
|
||||||
|
g_slist_free (pending);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
emit_in_idle (GFileMonitor *monitor,
|
emit_in_idle (GFileMonitor *monitor,
|
||||||
GFile *child,
|
GFile *child,
|
||||||
@ -355,10 +383,12 @@ emit_in_idle (GFileMonitor *monitor,
|
|||||||
{
|
{
|
||||||
GSource *source;
|
GSource *source;
|
||||||
FileChange *change;
|
FileChange *change;
|
||||||
|
GFileMonitorPrivate *priv;
|
||||||
|
|
||||||
|
priv = monitor->priv;
|
||||||
|
|
||||||
change = g_slice_new (FileChange);
|
change = g_slice_new (FileChange);
|
||||||
|
|
||||||
change->monitor = g_object_ref (monitor);
|
|
||||||
change->child = g_object_ref (child);
|
change->child = g_object_ref (child);
|
||||||
if (other_file)
|
if (other_file)
|
||||||
change->other_file = g_object_ref (other_file);
|
change->other_file = g_object_ref (other_file);
|
||||||
@ -366,12 +396,20 @@ emit_in_idle (GFileMonitor *monitor,
|
|||||||
change->other_file = NULL;
|
change->other_file = NULL;
|
||||||
change->event_type = event_type;
|
change->event_type = event_type;
|
||||||
|
|
||||||
source = g_idle_source_new ();
|
if (!priv->pending_file_change_id)
|
||||||
g_source_set_priority (source, 0);
|
{
|
||||||
|
source = g_idle_source_new ();
|
||||||
|
g_source_set_priority (source, 0);
|
||||||
|
|
||||||
g_source_set_callback (source, emit_cb, change, (GDestroyNotify)file_change_free);
|
/* We don't ref here - instead dispose will free any
|
||||||
g_source_attach (source, NULL);
|
* pending idles.
|
||||||
g_source_unref (source);
|
*/
|
||||||
|
g_source_set_callback (source, emit_cb, monitor, NULL);
|
||||||
|
priv->pending_file_change_id = g_source_attach (source, NULL);
|
||||||
|
g_source_unref (source);
|
||||||
|
}
|
||||||
|
/* We reverse this in the processor */
|
||||||
|
priv->pending_file_changes = g_slist_prepend (priv->pending_file_changes, change);
|
||||||
}
|
}
|
||||||
|
|
||||||
static guint32
|
static guint32
|
||||||
|
Loading…
Reference in New Issue
Block a user