1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright (C) 2006-2007 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 * Author: Alexander Larsson <alexl@redhat.com>
23 #include "gioenumtypes.h"
24 #include "glocalfilemonitor.h"
25 #include "giomodule-priv.h"
28 #include "glocalfile.h"
29 #include "glib-private.h"
33 #define DEFAULT_RATE_LIMIT 800 * G_TIME_SPAN_MILLISECOND
34 #define VIRTUAL_CHANGES_DONE_DELAY 2 * G_TIME_SPAN_SECOND
36 /* GFileMonitorSource is a GSource responsible for emitting the changed
37 * signals in the owner-context of the GFileMonitor.
39 * It contains functionality for cross-thread queuing of events. It
40 * also handles merging of CHANGED events and emission of CHANGES_DONE
43 * We use the "priv" pointer in the external struct to store it.
45 struct _GFileMonitorSource
{
50 GFileMonitorFlags flags
;
54 GSequence
*pending_changes
; /* sorted by ready time */
55 GHashTable
*pending_changes_table
;
60 /* PendingChange is a struct to keep track of a file that needs to have
61 * (at least) a CHANGES_DONE_HINT event sent for it in the near future.
63 * If 'dirty' is TRUE then a CHANGED event also needs to be sent.
65 * last_emission is the last time a CHANGED event was emitted. It is
66 * used to calculate the time to send the next event.
70 guint64 last_emission
: 63;
74 /* QueuedEvent is a signal that will be sent immediately, as soon as the
75 * source gets a chance to dispatch. The existence of any queued event
76 * implies that the source is ready now.
80 GFileMonitorEvent event_type
;
86 pending_change_get_ready_time (const PendingChange
*change
,
87 GFileMonitorSource
*fms
)
90 return change
->last_emission
+ fms
->rate_limit
;
92 return change
->last_emission
+ VIRTUAL_CHANGES_DONE_DELAY
;
96 pending_change_compare_ready_time (gconstpointer a_p
,
100 GFileMonitorSource
*fms
= user_data
;
101 const PendingChange
*a
= a_p
;
102 const PendingChange
*b
= b_p
;
106 ready_time_a
= pending_change_get_ready_time (a
, fms
);
107 ready_time_b
= pending_change_get_ready_time (b
, fms
);
109 if (ready_time_a
< ready_time_b
)
112 return ready_time_a
> ready_time_b
;
116 pending_change_free (gpointer data
)
118 PendingChange
*change
= data
;
120 g_free (change
->child
);
122 g_slice_free (PendingChange
, change
);
126 queued_event_free (QueuedEvent
*event
)
128 g_object_unref (event
->child
);
130 g_object_unref (event
->other
);
132 g_slice_free (QueuedEvent
, event
);
136 g_file_monitor_source_get_ready_time (GFileMonitorSource
*fms
)
140 if (fms
->event_queue
.length
)
143 iter
= g_sequence_get_begin_iter (fms
->pending_changes
);
144 if (g_sequence_iter_is_end (iter
))
147 return pending_change_get_ready_time (g_sequence_get (iter
), fms
);
151 g_file_monitor_source_update_ready_time (GFileMonitorSource
*fms
)
153 g_source_set_ready_time ((GSource
*) fms
, g_file_monitor_source_get_ready_time (fms
));
156 static GSequenceIter
*
157 g_file_monitor_source_find_pending_change (GFileMonitorSource
*fms
,
160 return g_hash_table_lookup (fms
->pending_changes_table
, child
);
164 g_file_monitor_source_add_pending_change (GFileMonitorSource
*fms
,
168 PendingChange
*change
;
171 change
= g_slice_new (PendingChange
);
172 change
->child
= g_strdup (child
);
173 change
->last_emission
= now
;
174 change
->dirty
= FALSE
;
176 iter
= g_sequence_insert_sorted (fms
->pending_changes
, change
, pending_change_compare_ready_time
, fms
);
177 g_hash_table_insert (fms
->pending_changes_table
, change
->child
, iter
);
181 g_file_monitor_source_set_pending_change_dirty (GFileMonitorSource
*fms
,
184 PendingChange
*change
;
186 change
= g_sequence_get (iter
);
188 /* if it was already dirty then this change is 'uninteresting' */
192 change
->dirty
= TRUE
;
194 g_sequence_sort_changed (iter
, pending_change_compare_ready_time
, fms
);
200 g_file_monitor_source_get_pending_change_dirty (GFileMonitorSource
*fms
,
203 PendingChange
*change
;
205 change
= g_sequence_get (iter
);
207 return change
->dirty
;
211 g_file_monitor_source_remove_pending_change (GFileMonitorSource
*fms
,
215 /* must remove the hash entry first -- its key is owned by the data
216 * which will be freed when removing the sequence iter
218 g_hash_table_remove (fms
->pending_changes_table
, child
);
219 g_sequence_remove (iter
);
223 g_file_monitor_source_queue_event (GFileMonitorSource
*fms
,
224 GFileMonitorEvent event_type
,
230 event
= g_slice_new (QueuedEvent
);
231 event
->event_type
= event_type
;
232 if (child
!= NULL
&& fms
->dirname
!= NULL
)
233 event
->child
= g_local_file_new_from_dirname_and_basename (fms
->dirname
, child
);
234 else if (child
!= NULL
)
236 gchar
*dirname
= g_path_get_dirname (fms
->filename
);
237 event
->child
= g_local_file_new_from_dirname_and_basename (dirname
, child
);
240 else if (fms
->dirname
)
241 event
->child
= _g_local_file_new (fms
->dirname
);
242 else if (fms
->filename
)
243 event
->child
= _g_local_file_new (fms
->filename
);
244 event
->other
= other
;
246 g_object_ref (other
);
248 g_queue_push_tail (&fms
->event_queue
, event
);
252 g_file_monitor_source_file_changed (GFileMonitorSource
*fms
,
256 GSequenceIter
*pending
;
257 gboolean interesting
;
259 pending
= g_file_monitor_source_find_pending_change (fms
, child
);
261 /* If there is no pending change, emit one and create a record,
262 * else: just mark the existing record as dirty.
266 g_file_monitor_source_queue_event (fms
, G_FILE_MONITOR_EVENT_CHANGED
, child
, NULL
);
267 g_file_monitor_source_add_pending_change (fms
, child
, now
);
271 interesting
= g_file_monitor_source_set_pending_change_dirty (fms
, pending
);
273 g_file_monitor_source_update_ready_time (fms
);
279 g_file_monitor_source_file_changes_done (GFileMonitorSource
*fms
,
282 GSequenceIter
*pending
;
284 pending
= g_file_monitor_source_find_pending_change (fms
, child
);
287 /* If it is dirty, make sure we push out the last CHANGED event */
288 if (g_file_monitor_source_get_pending_change_dirty (fms
, pending
))
289 g_file_monitor_source_queue_event (fms
, G_FILE_MONITOR_EVENT_CHANGED
, child
, NULL
);
291 g_file_monitor_source_queue_event (fms
, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT
, child
, NULL
);
292 g_file_monitor_source_remove_pending_change (fms
, pending
, child
);
297 g_file_monitor_source_file_created (GFileMonitorSource
*fms
,
301 /* Unlikely, but if we have pending changes for this filename, make
302 * sure we flush those out first, before creating the new ones.
304 g_file_monitor_source_file_changes_done (fms
, child
);
306 /* Emit CREATE and add a pending changes record */
307 g_file_monitor_source_queue_event (fms
, G_FILE_MONITOR_EVENT_CREATED
, child
, NULL
);
308 g_file_monitor_source_add_pending_change (fms
, child
, event_time
);
312 g_file_monitor_source_send_event (GFileMonitorSource
*fms
,
313 GFileMonitorEvent event_type
,
317 /* always flush any pending changes before we queue a new event */
318 g_file_monitor_source_file_changes_done (fms
, child
);
319 g_file_monitor_source_queue_event (fms
, event_type
, child
, other
);
323 g_file_monitor_source_send_synthetic_created (GFileMonitorSource
*fms
,
326 g_file_monitor_source_file_changes_done (fms
, child
);
327 g_file_monitor_source_queue_event (fms
, G_FILE_MONITOR_EVENT_CREATED
, child
, NULL
);
328 g_file_monitor_source_queue_event (fms
, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT
, child
, NULL
);
332 is_basename (const gchar
*name
)
334 if (name
[0] == '.' && ((name
[1] == '.' && name
[2] == '\0') || name
[1] == '\0'))
337 return !strchr (name
, '/');
341 g_file_monitor_source_handle_event (GFileMonitorSource
*fms
,
342 GFileMonitorEvent event_type
,
344 const gchar
*rename_to
,
348 gboolean interesting
= TRUE
;
350 g_assert (!child
|| is_basename (child
));
351 g_assert (!rename_to
|| is_basename (rename_to
));
353 if (fms
->basename
&& (!child
|| !g_str_equal (child
, fms
->basename
))
354 && (!rename_to
|| !g_str_equal (rename_to
, fms
->basename
)))
357 g_mutex_lock (&fms
->lock
);
359 /* monitor is already gone -- don't bother */
362 g_mutex_unlock (&fms
->lock
);
368 case G_FILE_MONITOR_EVENT_CREATED
:
369 g_assert (!other
&& !rename_to
);
370 g_file_monitor_source_file_created (fms
, child
, event_time
);
373 case G_FILE_MONITOR_EVENT_CHANGED
:
374 g_assert (!other
&& !rename_to
);
375 interesting
= g_file_monitor_source_file_changed (fms
, child
, event_time
);
378 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT
:
379 g_assert (!other
&& !rename_to
);
380 g_file_monitor_source_file_changes_done (fms
, child
);
383 case G_FILE_MONITOR_EVENT_MOVED_IN
:
384 g_assert (!rename_to
);
385 if (fms
->flags
& G_FILE_MONITOR_WATCH_MOVES
)
386 g_file_monitor_source_send_event (fms
, G_FILE_MONITOR_EVENT_MOVED_IN
, child
, other
);
388 g_file_monitor_source_send_synthetic_created (fms
, child
);
391 case G_FILE_MONITOR_EVENT_MOVED_OUT
:
392 g_assert (!rename_to
);
393 if (fms
->flags
& G_FILE_MONITOR_WATCH_MOVES
)
394 g_file_monitor_source_send_event (fms
, G_FILE_MONITOR_EVENT_MOVED_OUT
, child
, other
);
395 else if (other
&& (fms
->flags
& G_FILE_MONITOR_SEND_MOVED
))
396 g_file_monitor_source_send_event (fms
, G_FILE_MONITOR_EVENT_MOVED
, child
, other
);
398 g_file_monitor_source_send_event (fms
, G_FILE_MONITOR_EVENT_DELETED
, child
, NULL
);
401 case G_FILE_MONITOR_EVENT_RENAMED
:
402 g_assert (!other
&& rename_to
);
403 if (fms
->flags
& (G_FILE_MONITOR_WATCH_MOVES
| G_FILE_MONITOR_SEND_MOVED
))
406 const gchar
*dirname
;
407 gchar
*allocated_dirname
= NULL
;
408 GFileMonitorEvent event
;
410 event
= (fms
->flags
& G_FILE_MONITOR_WATCH_MOVES
) ? G_FILE_MONITOR_EVENT_RENAMED
: G_FILE_MONITOR_EVENT_MOVED
;
412 if (fms
->dirname
!= NULL
)
413 dirname
= fms
->dirname
;
416 allocated_dirname
= g_path_get_dirname (fms
->filename
);
417 dirname
= allocated_dirname
;
420 other
= g_local_file_new_from_dirname_and_basename (dirname
, rename_to
);
421 g_file_monitor_source_file_changes_done (fms
, rename_to
);
422 g_file_monitor_source_send_event (fms
, event
, child
, other
);
424 g_object_unref (other
);
425 g_free (allocated_dirname
);
429 g_file_monitor_source_send_event (fms
, G_FILE_MONITOR_EVENT_DELETED
, child
, NULL
);
430 g_file_monitor_source_send_synthetic_created (fms
, rename_to
);
434 case G_FILE_MONITOR_EVENT_DELETED
:
435 case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED
:
436 case G_FILE_MONITOR_EVENT_PRE_UNMOUNT
:
437 case G_FILE_MONITOR_EVENT_UNMOUNTED
:
438 g_assert (!other
&& !rename_to
);
439 g_file_monitor_source_send_event (fms
, event_type
, child
, NULL
);
442 case G_FILE_MONITOR_EVENT_MOVED
:
443 /* was never available in this API */
445 g_assert_not_reached ();
448 g_file_monitor_source_update_ready_time (fms
);
450 g_mutex_unlock (&fms
->lock
);
456 g_file_monitor_source_get_rate_limit (GFileMonitorSource
*fms
)
460 g_mutex_lock (&fms
->lock
);
461 rate_limit
= fms
->rate_limit
;
462 g_mutex_unlock (&fms
->lock
);
468 g_file_monitor_source_set_rate_limit (GFileMonitorSource
*fms
,
473 g_mutex_lock (&fms
->lock
);
475 if (rate_limit
!= fms
->rate_limit
)
477 fms
->rate_limit
= rate_limit
;
479 g_sequence_sort (fms
->pending_changes
, pending_change_compare_ready_time
, fms
);
480 g_file_monitor_source_update_ready_time (fms
);
487 g_mutex_unlock (&fms
->lock
);
493 g_file_monitor_source_dispatch (GSource
*source
,
494 GSourceFunc callback
,
497 GFileMonitorSource
*fms
= (GFileMonitorSource
*) source
;
502 /* make sure the monitor still exists */
506 now
= g_source_get_time (source
);
508 /* Acquire the lock once and grab all events in one go, handling the
509 * queued events first. This avoids strange possibilities in cases of
510 * long delays, such as CHANGED events coming before CREATED events.
512 * We do this by converting the applicable pending changes into queued
513 * events (after the ones already queued) and then stealing the entire
514 * event queue in one go.
516 g_mutex_lock (&fms
->lock
);
518 /* Create events for any pending changes that are due to fire */
519 while (!g_sequence_is_empty (fms
->pending_changes
))
521 GSequenceIter
*iter
= g_sequence_get_begin_iter (fms
->pending_changes
);
522 PendingChange
*pending
= g_sequence_get (iter
);
524 /* We've gotten to a pending change that's not ready. Stop. */
525 if (pending_change_get_ready_time (pending
, fms
) > now
)
530 /* It's time to send another CHANGED and update the record */
531 g_file_monitor_source_queue_event (fms
, G_FILE_MONITOR_EVENT_CHANGED
, pending
->child
, NULL
);
532 pending
->last_emission
= now
;
533 pending
->dirty
= FALSE
;
535 g_sequence_sort_changed (iter
, pending_change_compare_ready_time
, fms
);
539 /* It's time to send CHANGES_DONE and remove the pending record */
540 g_file_monitor_source_queue_event (fms
, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT
, pending
->child
, NULL
);
541 g_file_monitor_source_remove_pending_change (fms
, iter
, pending
->child
);
545 /* Steal the queue */
546 memcpy (&event_queue
, &fms
->event_queue
, sizeof event_queue
);
547 memset (&fms
->event_queue
, 0, sizeof fms
->event_queue
);
549 g_file_monitor_source_update_ready_time (fms
);
551 g_mutex_unlock (&fms
->lock
);
553 /* We now have our list of events to deliver */
554 while ((event
= g_queue_pop_head (&event_queue
)))
556 /* an event handler could destroy 'instance', so check each time */
558 g_file_monitor_emit_event (fms
->instance
, event
->child
, event
->other
, event
->event_type
);
560 queued_event_free (event
);
567 g_file_monitor_source_dispose (GFileMonitorSource
*fms
)
569 g_mutex_lock (&fms
->lock
);
577 g_hash_table_iter_init (&iter
, fms
->pending_changes_table
);
578 while (g_hash_table_iter_next (&iter
, NULL
, &seqiter
))
580 g_hash_table_iter_remove (&iter
);
581 g_sequence_remove (seqiter
);
584 while ((event
= g_queue_pop_head (&fms
->event_queue
)))
585 queued_event_free (event
);
587 g_assert (g_sequence_is_empty (fms
->pending_changes
));
588 g_assert (g_hash_table_size (fms
->pending_changes_table
) == 0);
589 g_assert (fms
->event_queue
.length
== 0);
590 fms
->instance
= NULL
;
592 g_file_monitor_source_update_ready_time (fms
);
595 g_mutex_unlock (&fms
->lock
);
597 g_source_destroy ((GSource
*) fms
);
601 g_file_monitor_source_finalize (GSource
*source
)
603 GFileMonitorSource
*fms
= (GFileMonitorSource
*) source
;
605 /* should already have been cleared in dispose of the monitor */
606 g_assert (fms
->instance
== NULL
);
607 g_assert (g_sequence_is_empty (fms
->pending_changes
));
608 g_assert (g_hash_table_size (fms
->pending_changes_table
) == 0);
609 g_assert (fms
->event_queue
.length
== 0);
611 g_hash_table_unref (fms
->pending_changes_table
);
612 g_sequence_free (fms
->pending_changes
);
614 g_free (fms
->dirname
);
615 g_free (fms
->basename
);
616 g_free (fms
->filename
);
618 g_mutex_clear (&fms
->lock
);
622 str_hash0 (gconstpointer str
)
624 return str
? g_str_hash (str
) : 0;
628 str_equal0 (gconstpointer a
,
631 return g_strcmp0 (a
, b
) == 0;
634 static GFileMonitorSource
*
635 g_file_monitor_source_new (gpointer instance
,
636 const gchar
*filename
,
637 gboolean is_directory
,
638 GFileMonitorFlags flags
)
640 static GSourceFuncs source_funcs
= {
642 g_file_monitor_source_dispatch
,
643 g_file_monitor_source_finalize
645 GFileMonitorSource
*fms
;
648 source
= g_source_new (&source_funcs
, sizeof (GFileMonitorSource
));
649 fms
= (GFileMonitorSource
*) source
;
651 g_source_set_name (source
, "GFileMonitorSource");
653 g_mutex_init (&fms
->lock
);
654 fms
->instance
= instance
;
655 fms
->pending_changes
= g_sequence_new (pending_change_free
);
656 fms
->pending_changes_table
= g_hash_table_new (str_hash0
, str_equal0
);
657 fms
->rate_limit
= DEFAULT_RATE_LIMIT
;
662 fms
->dirname
= g_strdup (filename
);
663 fms
->basename
= NULL
;
664 fms
->filename
= NULL
;
666 else if (flags
& G_FILE_MONITOR_WATCH_HARD_LINKS
)
669 fms
->basename
= NULL
;
670 fms
->filename
= g_strdup (filename
);
674 fms
->dirname
= g_path_get_dirname (filename
);
675 fms
->basename
= g_path_get_basename (filename
);
676 fms
->filename
= NULL
;
682 G_DEFINE_ABSTRACT_TYPE (GLocalFileMonitor
, g_local_file_monitor
, G_TYPE_FILE_MONITOR
)
690 g_local_file_monitor_get_property (GObject
*object
, guint prop_id
,
691 GValue
*value
, GParamSpec
*pspec
)
693 GLocalFileMonitor
*monitor
= G_LOCAL_FILE_MONITOR (object
);
696 g_assert (prop_id
== PROP_RATE_LIMIT
);
698 rate_limit
= g_file_monitor_source_get_rate_limit (monitor
->source
);
699 rate_limit
/= G_TIME_SPAN_MILLISECOND
;
701 g_value_set_int (value
, rate_limit
);
705 g_local_file_monitor_set_property (GObject
*object
, guint prop_id
,
706 const GValue
*value
, GParamSpec
*pspec
)
708 GLocalFileMonitor
*monitor
= G_LOCAL_FILE_MONITOR (object
);
711 g_assert (prop_id
== PROP_RATE_LIMIT
);
713 rate_limit
= g_value_get_int (value
);
714 rate_limit
*= G_TIME_SPAN_MILLISECOND
;
716 if (g_file_monitor_source_set_rate_limit (monitor
->source
, rate_limit
))
717 g_object_notify (object
, "rate-limit");
722 g_local_file_monitor_mounts_changed (GUnixMountMonitor
*mount_monitor
,
725 GLocalFileMonitor
*local_monitor
= user_data
;
726 GUnixMountEntry
*mount
;
730 /* Emulate unmount detection */
731 mount
= g_unix_mount_at (local_monitor
->source
->dirname
, NULL
);
733 is_mounted
= mount
!= NULL
;
736 g_unix_mount_free (mount
);
738 if (local_monitor
->was_mounted
!= is_mounted
)
740 if (local_monitor
->was_mounted
&& !is_mounted
)
742 file
= g_file_new_for_path (local_monitor
->source
->dirname
);
743 g_file_monitor_emit_event (G_FILE_MONITOR (local_monitor
), file
, NULL
, G_FILE_MONITOR_EVENT_UNMOUNTED
);
744 g_object_unref (file
);
746 local_monitor
->was_mounted
= is_mounted
;
752 g_local_file_monitor_start (GLocalFileMonitor
*local_monitor
,
753 const gchar
*filename
,
754 gboolean is_directory
,
755 GFileMonitorFlags flags
,
756 GMainContext
*context
)
758 GLocalFileMonitorClass
*class = G_LOCAL_FILE_MONITOR_GET_CLASS (local_monitor
);
759 GFileMonitorSource
*source
;
761 g_return_if_fail (G_IS_LOCAL_FILE_MONITOR (local_monitor
));
763 g_assert (!local_monitor
->source
);
765 source
= g_file_monitor_source_new (local_monitor
, filename
, is_directory
, flags
);
766 local_monitor
->source
= source
; /* owns the ref */
768 if (is_directory
&& !class->mount_notify
&& (flags
& G_FILE_MONITOR_WATCH_MOUNTS
))
771 /*claim everything was mounted */
772 local_monitor
->was_mounted
= TRUE
;
774 GUnixMountEntry
*mount
;
776 /* Emulate unmount detection */
778 mount
= g_unix_mount_at (local_monitor
->source
->dirname
, NULL
);
780 local_monitor
->was_mounted
= mount
!= NULL
;
783 g_unix_mount_free (mount
);
785 local_monitor
->mount_monitor
= g_unix_mount_monitor_get ();
786 g_signal_connect_object (local_monitor
->mount_monitor
, "mounts-changed",
787 G_CALLBACK (g_local_file_monitor_mounts_changed
), local_monitor
, 0);
791 G_LOCAL_FILE_MONITOR_GET_CLASS (local_monitor
)->start (local_monitor
,
792 source
->dirname
, source
->basename
, source
->filename
,
795 g_source_attach ((GSource
*) source
, context
);
799 g_local_file_monitor_dispose (GObject
*object
)
801 GLocalFileMonitor
*local_monitor
= G_LOCAL_FILE_MONITOR (object
);
803 g_file_monitor_source_dispose (local_monitor
->source
);
805 G_OBJECT_CLASS (g_local_file_monitor_parent_class
)->dispose (object
);
809 g_local_file_monitor_finalize (GObject
*object
)
811 GLocalFileMonitor
*local_monitor
= G_LOCAL_FILE_MONITOR (object
);
813 g_source_unref ((GSource
*) local_monitor
->source
);
815 G_OBJECT_CLASS (g_local_file_monitor_parent_class
)->finalize (object
);
819 g_local_file_monitor_init (GLocalFileMonitor
* local_monitor
)
823 static void g_local_file_monitor_class_init (GLocalFileMonitorClass
*class)
825 GObjectClass
*gobject_class
= G_OBJECT_CLASS (class);
827 gobject_class
->get_property
= g_local_file_monitor_get_property
;
828 gobject_class
->set_property
= g_local_file_monitor_set_property
;
829 gobject_class
->dispose
= g_local_file_monitor_dispose
;
830 gobject_class
->finalize
= g_local_file_monitor_finalize
;
832 g_object_class_override_property (gobject_class
, PROP_RATE_LIMIT
, "rate-limit");
835 static GLocalFileMonitor
*
836 g_local_file_monitor_new (gboolean is_remote_fs
,
839 GType type
= G_TYPE_INVALID
;
842 type
= _g_io_module_get_default_type (G_NFS_FILE_MONITOR_EXTENSION_POINT_NAME
,
843 "GIO_USE_FILE_MONITOR",
844 G_STRUCT_OFFSET (GLocalFileMonitorClass
, is_supported
));
846 if (type
== G_TYPE_INVALID
)
847 type
= _g_io_module_get_default_type (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME
,
848 "GIO_USE_FILE_MONITOR",
849 G_STRUCT_OFFSET (GLocalFileMonitorClass
, is_supported
));
851 if (type
== G_TYPE_INVALID
)
853 g_set_error_literal (error
, G_IO_ERROR
, G_IO_ERROR_FAILED
,
854 _("Unable to find default local file monitor type"));
858 return g_object_new (type
, NULL
);
862 g_local_file_monitor_new_for_path (const gchar
*pathname
,
863 gboolean is_directory
,
864 GFileMonitorFlags flags
,
867 GLocalFileMonitor
*monitor
;
868 gboolean is_remote_fs
;
870 is_remote_fs
= g_local_file_is_remote (pathname
);
872 monitor
= g_local_file_monitor_new (is_remote_fs
, error
);
875 g_local_file_monitor_start (monitor
, pathname
, is_directory
, flags
, g_main_context_get_thread_default ());
877 return G_FILE_MONITOR (monitor
);
881 g_local_file_monitor_new_in_worker (const gchar
*pathname
,
882 gboolean is_directory
,
883 GFileMonitorFlags flags
,
884 GFileMonitorCallback callback
,
888 GLocalFileMonitor
*monitor
;
889 gboolean is_remote_fs
;
891 is_remote_fs
= g_local_file_is_remote (pathname
);
893 monitor
= g_local_file_monitor_new (is_remote_fs
, error
);
898 g_signal_connect (monitor
, "changed", G_CALLBACK (callback
), user_data
);
900 g_local_file_monitor_start (monitor
, pathname
, is_directory
, flags
, GLIB_PRIVATE_CALL(g_get_worker_context
) ());
903 return G_FILE_MONITOR (monitor
);