/**
 * 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;
}
示例#3
0
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));
}
示例#4
0
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);
    }
}