X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgfilemonitor.c;h=c81f6fcb5bf4c9f98dbd6b63d286046e78e0eb0d;hb=2a2b11b1bb6c702d6b2ef1c37524a57688a94a4e;hp=f7a87b6f713599961f096412005ba1cafc0271bc;hpb=631d0c3534661e549f7df18fbb9832bdf19c5eaf;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gfilemonitor.c b/gio/gfilemonitor.c index f7a87b6..c81f6fc 100644 --- a/gio/gfilemonitor.c +++ b/gio/gfilemonitor.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: Alexander Larsson */ @@ -24,7 +22,6 @@ #include #include "gfilemonitor.h" -#include "gio-marshal.h" #include "gioenumtypes.h" #include "gfile.h" #include "gvfs.h" @@ -48,9 +45,9 @@ static void file_change_free (FileChange *change); * * To get informed about changes to the file or directory you are * monitoring, connect to the #GFileMonitor::changed signal. The - * signal will be emitted in the thread-default main - * context of the thread that the monitor was created in + * signal will be emitted in the + * [thread-default main context][g-main-context-push-thread-default] + * of the thread that the monitor was created in * (though if the global default main context is blocked, this may * cause notifications to be blocked even if the thread-default * context is still running). @@ -63,11 +60,6 @@ enum { LAST_SIGNAL }; -/* work around a limitation of the aliasing foo */ -#undef g_file_monitor - -G_DEFINE_ABSTRACT_TYPE (GFileMonitor, g_file_monitor, G_TYPE_OBJECT); - typedef struct { GFile *file; guint32 last_sent_change_time; /* 0 == not sent */ @@ -82,6 +74,7 @@ struct _GFileMonitorPrivate { /* Rate limiting change events */ GHashTable *rate_limiter; + GMutex mutex; GSource *pending_file_change_source; GSList *pending_file_changes; /* FileChange */ @@ -94,9 +87,15 @@ struct _GFileMonitorPrivate { enum { PROP_0, PROP_RATE_LIMIT, - PROP_CANCELLED + PROP_CANCELLED, + PROP_CONTEXT }; +/* work around a limitation of the aliasing foo */ +#undef g_file_monitor + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GFileMonitor, g_file_monitor, G_TYPE_OBJECT) + static void g_file_monitor_set_property (GObject *object, guint prop_id, @@ -113,6 +112,12 @@ g_file_monitor_set_property (GObject *object, g_file_monitor_set_rate_limit (monitor, g_value_get_int (value)); break; + case PROP_CONTEXT: + monitor->priv->context = g_value_dup_boxed (value); + if (monitor->priv->context == NULL) + monitor->priv->context = g_main_context_ref_thread_default (); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -176,8 +181,8 @@ g_file_monitor_finalize (GObject *object) g_hash_table_destroy (monitor->priv->rate_limiter); - if (monitor->priv->context) - g_main_context_unref (monitor->priv->context); + g_main_context_unref (monitor->priv->context); + g_mutex_clear (&monitor->priv->mutex); G_OBJECT_CLASS (g_file_monitor_parent_class)->finalize (object); } @@ -197,8 +202,7 @@ g_file_monitor_dispose (GObject *object) g_source_unref (priv->pending_file_change_source); priv->pending_file_change_source = NULL; } - g_slist_foreach (priv->pending_file_changes, (GFunc) file_change_free, NULL); - g_slist_free (priv->pending_file_changes); + g_slist_free_full (priv->pending_file_changes, (GDestroyNotify) file_change_free); priv->pending_file_changes = NULL; /* Make sure we cancel on last unref */ @@ -211,9 +215,7 @@ static void g_file_monitor_class_init (GFileMonitorClass *klass) { GObjectClass *object_class; - - g_type_class_add_private (klass, sizeof (GFileMonitorPrivate)); - + object_class = G_OBJECT_CLASS (klass); object_class->finalize = g_file_monitor_finalize; object_class->dispose = g_file_monitor_dispose; @@ -224,13 +226,13 @@ g_file_monitor_class_init (GFileMonitorClass *klass) * GFileMonitor::changed: * @monitor: a #GFileMonitor. * @file: a #GFile. - * @other_file: a #GFile or #NULL. + * @other_file: (allow-none): a #GFile or #NULL. * @event_type: a #GFileMonitorEvent. * * Emitted when @file has been changed. * * If using #G_FILE_MONITOR_SEND_MOVED flag and @event_type is - * #G_FILE_MONITOR_SEND_MOVED, @file will be set to a #GFile containing the + * #G_FILE_MONITOR_EVENT_MOVED, @file will be set to a #GFile containing the * old path, and @other_file will be set to a #GFile containing the new path. * * In all the other cases, @other_file will be set to #NULL. @@ -241,7 +243,7 @@ g_file_monitor_class_init (GFileMonitorClass *klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GFileMonitorClass, changed), NULL, NULL, - _gio_marshal_VOID__OBJECT_OBJECT_ENUM, + NULL, G_TYPE_NONE, 3, G_TYPE_FILE, G_TYPE_FILE, G_TYPE_FILE_MONITOR_EVENT); @@ -263,18 +265,24 @@ g_file_monitor_class_init (GFileMonitorClass *klass) FALSE, G_PARAM_READABLE| G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); + + g_object_class_install_property (object_class, + PROP_CONTEXT, + g_param_spec_boxed ("context", + P_("Context"), + P_("The main context to dispatch from"), + G_TYPE_MAIN_CONTEXT, G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); } static void g_file_monitor_init (GFileMonitor *monitor) { - monitor->priv = G_TYPE_INSTANCE_GET_PRIVATE (monitor, - G_TYPE_FILE_MONITOR, - GFileMonitorPrivate); + monitor->priv = g_file_monitor_get_instance_private (monitor); monitor->priv->rate_limit_msec = DEFAULT_RATE_LIMIT_MSECS; monitor->priv->rate_limiter = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, NULL, (GDestroyNotify) rate_limiter_free); - monitor->priv->context = g_main_context_get_thread_default (); + g_mutex_init (&monitor->priv->mutex); } /** @@ -377,7 +385,8 @@ emit_cb (gpointer data) { GFileMonitor *monitor = G_FILE_MONITOR (data); GSList *pending, *iter; - + + g_mutex_lock (&monitor->priv->mutex); pending = g_slist_reverse (monitor->priv->pending_file_changes); monitor->priv->pending_file_changes = NULL; if (monitor->priv->pending_file_change_source) @@ -385,11 +394,13 @@ emit_cb (gpointer data) g_source_unref (monitor->priv->pending_file_change_source); monitor->priv->pending_file_change_source = NULL; } + g_mutex_unlock (&monitor->priv->mutex); g_object_ref (monitor); 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); @@ -421,6 +432,7 @@ emit_in_idle (GFileMonitor *monitor, change->other_file = NULL; change->event_type = event_type; + g_mutex_lock (&monitor->priv->mutex); if (!priv->pending_file_change_source) { source = g_idle_source_new (); @@ -431,16 +443,18 @@ emit_in_idle (GFileMonitor *monitor, * pending idles. */ g_source_set_callback (source, emit_cb, monitor, NULL); + g_source_set_name (source, "[gio] emit_cb"); g_source_attach (source, monitor->priv->context); } /* We reverse this in the processor */ priv->pending_file_changes = g_slist_prepend (priv->pending_file_changes, change); + g_mutex_unlock (&monitor->priv->mutex); } static guint32 get_time_msecs (void) { - return g_thread_gettime() / (1000 * 1000); + return g_get_monotonic_time () / G_TIME_SPAN_MILLISECOND; } static guint32 @@ -512,7 +526,7 @@ calc_min_time (GFileMonitor *monitor, if (limiter->last_sent_change_time != 0) { - /* Set a timeout at 2*rate limit so that we can clear out the change from the hash eventualy */ + /* Set a timeout at 2*rate limit so that we can clear out the change from the hash eventually */ expire_at = limiter->last_sent_change_time + 2 * monitor->priv->rate_limit_msec; if (time_difference (time_now, expire_at) > 0) @@ -657,9 +671,8 @@ update_rate_limiter_timeout (GFileMonitor *monitor, * has taken place. Should be called from file monitor * implementations only. * - * The signal will be emitted from an idle handler (in the thread-default main - * context). + * The signal will be emitted from an idle handler (in the + * [thread-default main context][g-main-context-push-thread-default]). **/ void g_file_monitor_emit_event (GFileMonitor *monitor, @@ -720,7 +733,7 @@ g_file_monitor_emit_event (GFileMonitor *monitor, limiter->last_sent_change_time = time_now; limiter->send_delayed_change_at = 0; - /* Set a timeout of 2*rate limit so that we can clear out the change from the hash eventualy */ + /* Set a timeout of 2*rate limit so that we can clear out the change from the hash eventually */ update_rate_limiter_timeout (monitor, time_now + 2 * monitor->priv->rate_limit_msec); }