X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgfilemonitor.c;h=c81f6fcb5bf4c9f98dbd6b63d286046e78e0eb0d;hb=e55a953642a9e402f4363f9fa347b6061dd78990;hp=38a0493bcde341adb52608a854131104192d0cc5;hpb=73ca8b47540d005d5227c03aac143d6780da654c;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gfilemonitor.c b/gio/gfilemonitor.c index 38a0493..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,10 +226,16 @@ g_file_monitor_class_init (GFileMonitorClass *klass) * GFileMonitor::changed: * @monitor: a #GFileMonitor. * @file: a #GFile. - * @other_file: a #GFile. + * @other_file: (allow-none): a #GFile or #NULL. * @event_type: a #GFileMonitorEvent. - * - * Emitted when a file has been changed. + * + * Emitted when @file has been changed. + * + * If using #G_FILE_MONITOR_SEND_MOVED flag and @event_type is + * #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. **/ signals[CHANGED] = g_signal_new (I_("changed"), @@ -235,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); @@ -257,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); } /** @@ -327,21 +341,21 @@ g_file_monitor_cancel (GFileMonitor* monitor) /** * g_file_monitor_set_rate_limit: * @monitor: a #GFileMonitor. - * @limit_msecs: a integer with the limit in milliseconds to - * poll for changes. + * @limit_msecs: a non-negative integer with the limit in milliseconds + * to poll for changes * * Sets the rate limit to which the @monitor will report - * consecutive change events to the same file. - * - **/ + * consecutive change events to the same file. + */ void g_file_monitor_set_rate_limit (GFileMonitor *monitor, - int limit_msecs) + gint limit_msecs) { GFileMonitorPrivate *priv; - + g_return_if_fail (G_IS_FILE_MONITOR (monitor)); - + g_return_if_fail (limit_msecs >= 0); + priv = monitor->priv; if (priv->rate_limit_msec != limit_msecs) { @@ -371,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) @@ -379,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); @@ -415,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 (); @@ -425,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 @@ -506,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) @@ -651,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, @@ -714,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); }