Commit fe76f3bf authored by Christian Hergert's avatar Christian Hergert

generator: add threading and async API

By using an async API for generation, we allow ourselves to run the generators in a thread-pool, giving ourselves a chance at a healthy speed up in generation.
parent 4468ac6f
......@@ -310,25 +310,55 @@ girst_generator_generate_repository (GirstGenerator *self,
return TRUE;
}
gboolean
girst_generator_generate (GirstGenerator *self,
GCancellable *cancellable,
GError **error)
static void
girst_generator_generate_worker (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
{
g_return_val_if_fail (GIRST_IS_GENERATOR (self), FALSE);
g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
GirstGenerator *self = source_object;
g_autoptr(GError) error = NULL;
g_assert (G_IS_TASK (task));
g_assert (GIRST_IS_GENERATOR (self));
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
errno = 0;
if (g_mkdir_with_parents (self->outdir, 0750) != 0)
{
g_set_error_literal (error,
G_FILE_ERROR,
g_file_error_from_errno (errno),
g_strerror (errno));
return FALSE;
}
g_task_return_new_error (task,
G_FILE_ERROR,
g_file_error_from_errno (errno),
"%s", g_strerror (errno));
if (!girst_generator_generate_repository (self, self->repository, &error))
g_task_return_error (task, g_steal_pointer (&error));
else
g_task_return_boolean (task, TRUE);
}
if (!girst_generator_generate_repository (self, self->repository, error))
return FALSE;
void
girst_generator_generate_async (GirstGenerator *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr(GTask) task = NULL;
return TRUE;
g_return_if_fail (GIRST_IS_GENERATOR (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, girst_generator_generate_async);
g_task_run_in_thread (task, girst_generator_generate_worker);
}
gboolean
girst_generator_generate_finish (GirstGenerator *self,
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (GIRST_IS_GENERATOR (self), FALSE);
g_return_val_if_fail (G_IS_TASK (result), FALSE);
return g_task_propagate_boolean (G_TASK (result), error);
}
......@@ -27,11 +27,15 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (GirstGenerator, girst_generator, GIRST, GENERATOR, GObject)
GirstGenerator *girst_generator_new (GirstRepository *repository,
const gchar *outdir,
GirstLanguage language);
gboolean girst_generator_generate (GirstGenerator *self,
GCancellable *cancellable,
GError **error);
GirstGenerator *girst_generator_new (GirstRepository *repository,
const gchar *outdir,
GirstLanguage language);
void girst_generator_generate_async (GirstGenerator *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean girst_generator_generate_finish (GirstGenerator *self,
GAsyncResult *result,
GError **error);
G_END_DECLS
......@@ -32,6 +32,8 @@
static gchar *language;
static gchar *outdir;
static gchar **girdirs;
static gint exit_code = EXIT_SUCCESS;
static gint active;
static const GOptionEntry main_entries[] = {
{ "outdir", 'o', 0, G_OPTION_ARG_FILENAME, &outdir,
"Location to store generated files",
......@@ -45,6 +47,27 @@ static const GOptionEntry main_entries[] = {
{ NULL }
};
static void
girst_main_generate_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GirstGenerator *generator = (GirstGenerator *)object;
g_autoptr(GMainLoop) main_loop = user_data;
g_autoptr(GError) error = NULL;
g_assert (GIRST_IS_GENERATOR (generator));
g_assert (main_loop != NULL);
if (!girst_generator_generate_finish (generator, result, &error))
g_error ("%s", error->message);
active--;
if (active == 0)
g_main_loop_quit (main_loop);
}
static void
foreach_repository_cb (gpointer data,
gpointer user_data)
......@@ -52,23 +75,18 @@ foreach_repository_cb (gpointer data,
g_autoptr(GirstGenerator) generator = NULL;
GirstRepository *repository = data;
g_autoptr(GError) error = NULL;
gint *exit_code = user_data;
GMainLoop *main_loop = user_data;
g_assert (GIRST_IS_REPOSITORY (repository));
g_assert (exit_code != NULL);
g_assert (main_loop != NULL);
if (*exit_code != EXIT_SUCCESS)
return;
active++;
generator = girst_generator_new (repository, outdir, GIRST_LANGUAGE_C);
if (!girst_generator_generate (generator, NULL, &error))
{
g_printerr ("Error processing %s: %s\n",
(gchar *)g_object_get_data (G_OBJECT (repository), "NAME"),
error->message);
*exit_code = EXIT_FAILURE;
}
girst_generator_generate_async (generator,
NULL,
girst_main_generate_cb,
g_main_loop_ref (main_loop));
}
static GFile *
......@@ -148,7 +166,7 @@ main (gint argc,
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GHashTable) loaded = NULL;
g_autoptr(GError) error = NULL;
gint exit_code = EXIT_SUCCESS;
g_autoptr(GMainLoop) main_loop = NULL;
girst_parser_ensure_types ();
......@@ -174,6 +192,8 @@ main (gint argc,
return EXIT_FAILURE;
}
main_loop = g_main_loop_new (NULL, FALSE);
g_irepository_prepend_search_path (".");
g_irepository_require (g_irepository_get_default (), "Girst", "1.0", 0, NULL);
......@@ -223,7 +243,9 @@ main (gint argc,
}
}
girst_cache_foreach (foreach_repository_cb, &exit_code);
girst_cache_foreach (foreach_repository_cb, main_loop);
g_main_loop_run (main_loop);
return exit_code;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment