/** * ide_clang_service_get_translation_unit_async: * * This function is used to asynchronously retrieve the translation unit for * a particular file. * * If the translation unit is up to date, then no parsing will occur and the * existing translation unit will be used. * * If the translation unit is out of date, then the source file(s) will be * parsed via clang_parseTranslationUnit() asynchronously. */ void ide_clang_service_get_translation_unit_async (IdeClangService *self, IdeFile *file, gint64 min_serial, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { IdeClangTranslationUnit *cached; g_autoptr(GTask) task = NULL; g_return_if_fail (IDE_IS_CLANG_SERVICE (self)); g_return_if_fail (IDE_IS_FILE (file)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); task = g_task_new (self, cancellable, callback, user_data); /* * Clang likes to crash on our temporary files. */ if (ide_file_get_is_temporary (file)) { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "File does not yet exist, ignoring translation unit request."); return; } if (min_serial == 0) { IdeContext *context; IdeUnsavedFiles *unsaved_files; context = ide_object_get_context (IDE_OBJECT (self)); unsaved_files = ide_context_get_unsaved_files (context); min_serial = ide_unsaved_files_get_sequence (unsaved_files); } /* * If we have a cached unit, and it is new enough, then re-use it. */ if ((cached = egg_task_cache_peek (self->units_cache, file)) && (ide_clang_translation_unit_get_serial (cached) >= min_serial)) { g_task_return_pointer (task, g_object_ref (cached), g_object_unref); return; } egg_task_cache_get_async (self->units_cache, file, TRUE, cancellable, ide_clang_service_get_translation_unit_cb, g_object_ref (task)); }
/** * ide_clang_service_get_cached_translation_unit: * @self: A #IdeClangService. * * Gets a cached translation unit if one exists for the file. * * Returns: (transfer full) (nullable): An #IdeClangTranslationUnit or %NULL. */ IdeClangTranslationUnit * ide_clang_service_get_cached_translation_unit (IdeClangService *self, IdeFile *file) { IdeClangTranslationUnit *cached; g_return_val_if_fail (IDE_IS_CLANG_SERVICE (self), NULL); g_return_val_if_fail (IDE_IS_FILE (file), NULL); cached = egg_task_cache_peek (self->units_cache, file); return cached ? g_object_ref (cached) : NULL; }
static void ide_gettext_diagnostic_provider_diagnose_async (IdeDiagnosticProvider *provider, IdeFile *file, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { IdeGettextDiagnosticProvider *self = (IdeGettextDiagnosticProvider *)provider; g_autoptr(IdeUnsavedFile) unsaved_file = NULL; IdeGettextDiagnostics *cached; g_autoptr(GTask) task = NULL; g_return_if_fail (IDE_IS_GETTEXT_DIAGNOSTIC_PROVIDER (self)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); task = g_task_new (self, cancellable, callback, user_data); g_task_set_source_tag (task, ide_gettext_diagnostic_provider_diagnose_async); if (NULL != (cached = egg_task_cache_peek (self->diagnostics_cache, file))) { unsaved_file = get_unsaved_file (self, file); if (unsaved_file == NULL || (cached->sequence >= ide_unsaved_file_get_sequence (unsaved_file))) { g_task_return_pointer (task, g_object_ref (cached), g_object_unref); return; } } egg_task_cache_get_async (self->diagnostics_cache, file, TRUE, cancellable, get_diagnostics_cb, g_steal_pointer (&task)); }
void egg_task_cache_get_async (EggTaskCache *self, gconstpointer key, gboolean force_update, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_autoptr(GTask) task = NULL; GPtrArray *queued; gpointer ret; g_return_if_fail (EGG_IS_TASK_CACHE (self)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); task = g_task_new (self, cancellable, callback, user_data); /* * If we have the answer, return it now. */ if (!force_update && (ret = egg_task_cache_peek (self, key))) { g_task_return_pointer (task, self->value_copy_func (ret), self->value_destroy_func); return; } EGG_COUNTER_INC (misses); /* * Always queue the request. If we need to dispatch the worker to * fetch the result, that will happen with another task. */ if (!(queued = g_hash_table_lookup (self->queued, key))) { queued = g_ptr_array_new_with_free_func (g_object_unref); g_hash_table_insert (self->queued, self->key_copy_func ((gpointer)key), queued); } g_ptr_array_add (queued, g_object_ref (task)); EGG_COUNTER_INC (queued); /* * The in_flight hashtable will have a bit set if we have queued * an operation for this key. */ if (!g_hash_table_contains (self->in_flight, key)) { g_autoptr(GTask) fetch_task = NULL; fetch_task = g_task_new (self, cancellable, egg_task_cache_fetch_cb, self->key_copy_func ((gpointer)key)); g_hash_table_insert (self->in_flight, self->key_copy_func ((gpointer)key), GINT_TO_POINTER (TRUE)); self->populate_callback (self, key, g_object_ref (fetch_task), self->populate_callback_data); EGG_COUNTER_INC (in_flight); } }