static void g_file_monitor_source_dispose (GFileMonitorSource *fms) { g_mutex_lock (&fms->lock); if (fms->instance) { GHashTableIter iter; gpointer seqiter; QueuedEvent *event; g_hash_table_iter_init (&iter, fms->pending_changes_table); while (g_hash_table_iter_next (&iter, NULL, &seqiter)) { g_hash_table_iter_remove (&iter); g_sequence_remove (seqiter); } while ((event = g_queue_pop_head (&fms->event_queue))) queued_event_free (event); g_assert (g_sequence_is_empty (fms->pending_changes)); g_assert (g_hash_table_size (fms->pending_changes_table) == 0); g_assert (fms->event_queue.length == 0); fms->instance = NULL; g_file_monitor_source_update_ready_time (fms); } g_mutex_unlock (&fms->lock); g_source_destroy ((GSource *) fms); }
static void g_menu_exporter_group_subscribe (GMenuExporterGroup *group, GVariantBuilder *builder) { GHashTableIter iter; gpointer key, val; if (!group->prepared) { GMenuExporterMenu *menu; /* set this first, so that any menus created during the * preparation of the first menu also end up in the prepared * state. * */ group->prepared = TRUE; menu = g_hash_table_lookup (group->menus, 0); /* If the group was created by a subscription and does not yet * exist, it won't have a root menu... * * That menu will be prepared if it is ever added (due to * group->prepared == TRUE). */ if (menu) g_menu_exporter_menu_prepare (menu); } group->subscribed++; g_hash_table_iter_init (&iter, group->menus); while (g_hash_table_iter_next (&iter, &key, &val)) { guint id = GPOINTER_TO_INT (key); GMenuExporterMenu *menu = val; if (!g_sequence_is_empty (menu->item_links)) { g_variant_builder_open (builder, G_VARIANT_TYPE ("(uuaa{sv})")); g_variant_builder_add (builder, "u", group->id); g_variant_builder_add (builder, "u", id); g_variant_builder_add_value (builder, g_menu_exporter_menu_list (menu)); g_variant_builder_close (builder); } } }
static void g_file_monitor_source_finalize (GSource *source) { GFileMonitorSource *fms = (GFileMonitorSource *) source; /* should already have been cleared in dispose of the monitor */ g_assert (fms->instance == NULL); g_assert (g_sequence_is_empty (fms->pending_changes)); g_assert (g_hash_table_size (fms->pending_changes_table) == 0); g_assert (fms->event_queue.length == 0); g_hash_table_unref (fms->pending_changes_table); g_sequence_free (fms->pending_changes); g_free (fms->dirname); g_free (fms->basename); g_free (fms->filename); g_mutex_clear (&fms->lock); }
static gboolean g_file_monitor_source_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) { GFileMonitorSource *fms = (GFileMonitorSource *) source; QueuedEvent *event; GQueue event_queue; gint64 now; /* make sure the monitor still exists */ if (!fms->instance) return FALSE; now = g_source_get_time (source); /* Acquire the lock once and grab all events in one go, handling the * queued events first. This avoids strange possibilities in cases of * long delays, such as CHANGED events coming before CREATED events. * * We do this by converting the applicable pending changes into queued * events (after the ones already queued) and then stealing the entire * event queue in one go. */ g_mutex_lock (&fms->lock); /* Create events for any pending changes that are due to fire */ while (!g_sequence_is_empty (fms->pending_changes)) { GSequenceIter *iter = g_sequence_get_begin_iter (fms->pending_changes); PendingChange *pending = g_sequence_get (iter); /* We've gotten to a pending change that's not ready. Stop. */ if (pending_change_get_ready_time (pending, fms) > now) break; if (pending->dirty) { /* It's time to send another CHANGED and update the record */ g_file_monitor_source_queue_event (fms, G_FILE_MONITOR_EVENT_CHANGED, pending->child, NULL); pending->last_emission = now; pending->dirty = FALSE; g_sequence_sort_changed (iter, pending_change_compare_ready_time, fms); } else { /* It's time to send CHANGES_DONE and remove the pending record */ g_file_monitor_source_queue_event (fms, G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT, pending->child, NULL); g_file_monitor_source_remove_pending_change (fms, iter, pending->child); } } /* Steal the queue */ memcpy (&event_queue, &fms->event_queue, sizeof event_queue); memset (&fms->event_queue, 0, sizeof fms->event_queue); g_file_monitor_source_update_ready_time (fms); g_mutex_unlock (&fms->lock); /* We now have our list of events to deliver */ while ((event = g_queue_pop_head (&event_queue))) { /* an event handler could destroy 'instance', so check each time */ if (fms->instance) g_file_monitor_emit_event (fms->instance, event->child, event->other, event->event_type); queued_event_free (event); } return TRUE; }