From e46fdc714e8c88b42e12d0a637f1da688b4e7e9a Mon Sep 17 00:00:00 2001 From: Ell Date: Mon, 1 Oct 2018 05:13:45 -0400 Subject: [PATCH] app: in gimp-parallel, cancel ongoing async operations upon exit When shutting-down gimp-parallel, cancel and/or abort any ongoing and queued async operations, instead of finishing them (async operations that already started executing will be canceled, but execution will be blocked until they're finished.) This is especially important since we're shutting down gimp-parallel before the destruction of data factories. This commit causes any ongoing async operations of the factories to be canceled on shutdown, rather than waiting for them to finish normally. --- app/core/gimp-parallel.cc | 55 ++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/app/core/gimp-parallel.cc b/app/core/gimp-parallel.cc index 5ebad358ff..bad87b2292 100644 --- a/app/core/gimp-parallel.cc +++ b/app/core/gimp-parallel.cc @@ -42,6 +42,7 @@ extern "C" #include "gimp.h" #include "gimp-parallel.h" #include "gimpasync.h" +#include "gimpcancelable.h" #define GIMP_PARALLEL_MAX_THREADS 64 @@ -60,9 +61,11 @@ typedef struct typedef struct { - GThread *thread; + GThread *thread; - gboolean quit; + gboolean quit; + + GimpAsync *current_async; } GimpParallelRunAsyncThread; typedef struct @@ -89,9 +92,11 @@ typedef struct static void gimp_parallel_notify_num_processors (GimpGeglConfig *config); -static void gimp_parallel_set_n_threads (gint n_threads); +static void gimp_parallel_set_n_threads (gint n_threads, + gboolean finish_tasks); -static void gimp_parallel_run_async_set_n_threads (gint n_threads); +static void gimp_parallel_run_async_set_n_threads (gint n_threads, + gboolean finish_tasks); static gpointer gimp_parallel_run_async_thread_func (GimpParallelRunAsyncThread *thread); static void gimp_parallel_run_async_execute_task (GimpParallelRunAsyncTask *task); static void gimp_parallel_run_async_cancel (GimpAsync *async); @@ -147,7 +152,7 @@ gimp_parallel_exit (Gimp *gimp) NULL); /* stop all threads */ - gimp_parallel_set_n_threads (0); + gimp_parallel_set_n_threads (0, /* finish_tasks = */ FALSE); } GimpAsync * @@ -441,18 +446,21 @@ gimp_parallel_distribute_area (const GeglRectangle *area, static void gimp_parallel_notify_num_processors (GimpGeglConfig *config) { - gimp_parallel_set_n_threads (config->num_processors); + gimp_parallel_set_n_threads (config->num_processors, + /* finish_tasks = */ TRUE); } static void -gimp_parallel_set_n_threads (gint n_threads) +gimp_parallel_set_n_threads (gint n_threads, + gboolean finish_tasks) { - gimp_parallel_run_async_set_n_threads (n_threads); + gimp_parallel_run_async_set_n_threads (n_threads, finish_tasks); gimp_parallel_distribute_set_n_threads (n_threads); } static void -gimp_parallel_run_async_set_n_threads (gint n_threads) +gimp_parallel_run_async_set_n_threads (gint n_threads, + gboolean finish_tasks) { gint i; @@ -483,6 +491,9 @@ gimp_parallel_run_async_set_n_threads (gint n_threads) &gimp_parallel_run_async_threads[i]; thread->quit = TRUE; + + if (thread->current_async && ! finish_tasks) + gimp_cancelable_cancel (GIMP_CANCELABLE (thread->current_async)); } g_cond_broadcast (&gimp_parallel_run_async_cond); @@ -511,7 +522,21 @@ gimp_parallel_run_async_set_n_threads (gint n_threads) g_object_set_data (G_OBJECT (task->async), "gimp-parallel-run-async-link", NULL); - gimp_parallel_run_async_execute_task (task); + if (finish_tasks) + { + gimp_parallel_run_async_execute_task (task); + } + else + { + if (task->user_data && task->user_data_destroy_func) + task->user_data_destroy_func (task->user_data); + + gimp_async_abort (task->async); + + g_object_unref (task->async); + + g_slice_free (GimpParallelRunAsyncTask, task); + } } } } @@ -533,11 +558,15 @@ gimp_parallel_run_async_thread_func (GimpParallelRunAsyncThread *thread) g_object_set_data (G_OBJECT (task->async), "gimp-parallel-run-async-link", NULL); + thread->current_async = GIMP_ASYNC (g_object_ref (task->async)); + g_mutex_unlock (&gimp_parallel_run_async_mutex); gimp_parallel_run_async_execute_task (task); g_mutex_lock (&gimp_parallel_run_async_mutex); + + g_clear_object (&thread->current_async); } if (thread->quit) @@ -571,6 +600,12 @@ gimp_parallel_run_async_cancel (GimpAsync *async) GList *link; GimpParallelRunAsyncTask *task = NULL; + link = (GList *) g_object_get_data (G_OBJECT (async), + "gimp-parallel-run-async-link"); + + if (! link) + return; + g_mutex_lock (&gimp_parallel_run_async_mutex); link = (GList *) g_object_get_data (G_OBJECT (async),