mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 03:16:17 +01:00
gtask: Add a g_task_set_name() method
Similarly to g_source_set_name(), this sets a name on a GTask for debugging and profiling. Importantly, this name is propagated to the GSource for idle callbacks for the GTask, ending the glorious reign of `[gio] complete_in_idle_cb`. The name can be queried using g_task_get_name(). Locking is avoided by only allowing the name to be set before the GTask is used from another thread. Includes tests. Signed-off-by: Philip Withnall <withnall@endlessm.com>
This commit is contained in:
parent
f65adb48e1
commit
e89128a935
@ -4396,6 +4396,7 @@ g_task_set_priority
|
|||||||
g_task_set_check_cancellable
|
g_task_set_check_cancellable
|
||||||
g_task_set_return_on_cancel
|
g_task_set_return_on_cancel
|
||||||
g_task_set_source_tag
|
g_task_set_source_tag
|
||||||
|
g_task_set_name
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
g_task_report_error
|
g_task_report_error
|
||||||
g_task_report_new_error
|
g_task_report_new_error
|
||||||
@ -4408,6 +4409,7 @@ g_task_get_return_on_cancel
|
|||||||
g_task_get_context
|
g_task_get_context
|
||||||
g_task_get_source_object
|
g_task_get_source_object
|
||||||
g_task_get_source_tag
|
g_task_get_source_tag
|
||||||
|
g_task_get_name
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
g_task_return_boolean
|
g_task_return_boolean
|
||||||
g_task_return_int
|
g_task_return_int
|
||||||
|
54
gio/gtask.c
54
gio/gtask.c
@ -543,6 +543,7 @@ struct _GTask {
|
|||||||
|
|
||||||
gpointer source_object;
|
gpointer source_object;
|
||||||
gpointer source_tag;
|
gpointer source_tag;
|
||||||
|
gchar *name; /* (owned); may only be modified before the #GTask is threaded */
|
||||||
|
|
||||||
gpointer task_data;
|
gpointer task_data;
|
||||||
GDestroyNotify task_data_destroy;
|
GDestroyNotify task_data_destroy;
|
||||||
@ -637,6 +638,7 @@ g_task_finalize (GObject *object)
|
|||||||
|
|
||||||
g_clear_object (&task->source_object);
|
g_clear_object (&task->source_object);
|
||||||
g_clear_object (&task->cancellable);
|
g_clear_object (&task->cancellable);
|
||||||
|
g_free (task->name);
|
||||||
|
|
||||||
if (task->context)
|
if (task->context)
|
||||||
g_main_context_unref (task->context);
|
g_main_context_unref (task->context);
|
||||||
@ -978,6 +980,36 @@ g_task_set_source_tag (GTask *task,
|
|||||||
TRACE (GIO_TASK_SET_SOURCE_TAG (task, source_tag));
|
TRACE (GIO_TASK_SET_SOURCE_TAG (task, source_tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_task_set_name:
|
||||||
|
* @task: a #GTask
|
||||||
|
* @name: (nullable): a human readable name for the task, or %NULL to unset it
|
||||||
|
*
|
||||||
|
* Sets @task’s name, used in debugging and profiling. The name defaults to
|
||||||
|
* %NULL.
|
||||||
|
*
|
||||||
|
* The task name should describe in a human readable way what the task does.
|
||||||
|
* For example, ‘Open file’ or ‘Connect to network host’. It is used to set the
|
||||||
|
* name of the #GSource used for idle completion of the task.
|
||||||
|
*
|
||||||
|
* This function may only be called before the @task is first used in a thread
|
||||||
|
* other than the one it was constructed in.
|
||||||
|
*
|
||||||
|
* Since: 2.60
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_task_set_name (GTask *task,
|
||||||
|
const gchar *name)
|
||||||
|
{
|
||||||
|
gchar *new_name;
|
||||||
|
|
||||||
|
g_return_if_fail (G_IS_TASK (task));
|
||||||
|
|
||||||
|
new_name = g_strdup (name);
|
||||||
|
g_free (task->name);
|
||||||
|
task->name = g_steal_pointer (&new_name);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_task_get_source_object:
|
* g_task_get_source_object:
|
||||||
* @task: a #GTask
|
* @task: a #GTask
|
||||||
@ -1138,6 +1170,22 @@ g_task_get_source_tag (GTask *task)
|
|||||||
return task->source_tag;
|
return task->source_tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_task_get_name:
|
||||||
|
* @task: a #GTask
|
||||||
|
*
|
||||||
|
* Gets @task’s name. See g_task_set_name().
|
||||||
|
*
|
||||||
|
* Returns: (nullable) (transfer none): @task’s name, or %NULL
|
||||||
|
* Since: 2.60
|
||||||
|
*/
|
||||||
|
const gchar *
|
||||||
|
g_task_get_name (GTask *task)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (G_IS_TASK (task), NULL);
|
||||||
|
|
||||||
|
return task->name;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
g_task_return_now (GTask *task)
|
g_task_return_now (GTask *task)
|
||||||
@ -1527,6 +1575,9 @@ g_task_run_in_thread_sync (GTask *task,
|
|||||||
* #GMainContext with @task's [priority][io-priority], and sets @source's
|
* #GMainContext with @task's [priority][io-priority], and sets @source's
|
||||||
* callback to @callback, with @task as the callback's `user_data`.
|
* callback to @callback, with @task as the callback's `user_data`.
|
||||||
*
|
*
|
||||||
|
* It will set the @source’s name to the task’s name (as set with
|
||||||
|
* g_task_set_name()), if one has been set.
|
||||||
|
*
|
||||||
* This takes a reference on @task until @source is destroyed.
|
* This takes a reference on @task until @source is destroyed.
|
||||||
*
|
*
|
||||||
* Since: 2.36
|
* Since: 2.36
|
||||||
@ -1541,6 +1592,9 @@ g_task_attach_source (GTask *task,
|
|||||||
g_source_set_callback (source, callback,
|
g_source_set_callback (source, callback,
|
||||||
g_object_ref (task), g_object_unref);
|
g_object_ref (task), g_object_unref);
|
||||||
g_source_set_priority (source, task->priority);
|
g_source_set_priority (source, task->priority);
|
||||||
|
if (task->name != NULL)
|
||||||
|
g_source_set_name (source, task->name);
|
||||||
|
|
||||||
g_source_attach (source, task->context);
|
g_source_attach (source, task->context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +74,9 @@ void g_task_set_check_cancellable (GTask *task,
|
|||||||
GLIB_AVAILABLE_IN_2_36
|
GLIB_AVAILABLE_IN_2_36
|
||||||
void g_task_set_source_tag (GTask *task,
|
void g_task_set_source_tag (GTask *task,
|
||||||
gpointer source_tag);
|
gpointer source_tag);
|
||||||
|
GLIB_AVAILABLE_IN_2_60
|
||||||
|
void g_task_set_name (GTask *task,
|
||||||
|
const gchar *name);
|
||||||
|
|
||||||
GLIB_AVAILABLE_IN_2_36
|
GLIB_AVAILABLE_IN_2_36
|
||||||
gpointer g_task_get_source_object (GTask *task);
|
gpointer g_task_get_source_object (GTask *task);
|
||||||
@ -89,6 +92,8 @@ GLIB_AVAILABLE_IN_2_36
|
|||||||
gboolean g_task_get_check_cancellable (GTask *task);
|
gboolean g_task_get_check_cancellable (GTask *task);
|
||||||
GLIB_AVAILABLE_IN_2_36
|
GLIB_AVAILABLE_IN_2_36
|
||||||
gpointer g_task_get_source_tag (GTask *task);
|
gpointer g_task_get_source_tag (GTask *task);
|
||||||
|
GLIB_AVAILABLE_IN_2_60
|
||||||
|
const gchar *g_task_get_name (GTask *task);
|
||||||
|
|
||||||
GLIB_AVAILABLE_IN_2_36
|
GLIB_AVAILABLE_IN_2_36
|
||||||
gboolean g_task_is_valid (gpointer result,
|
gboolean g_task_is_valid (gpointer result,
|
||||||
|
@ -614,6 +614,46 @@ test_priority (void)
|
|||||||
g_assert_cmpint (ret3, ==, 3);
|
g_assert_cmpint (ret3, ==, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Test that getting and setting the task name works. */
|
||||||
|
static void name_callback (GObject *object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_name (void)
|
||||||
|
{
|
||||||
|
GTask *t1 = NULL;
|
||||||
|
gchar *name1 = NULL;
|
||||||
|
|
||||||
|
t1 = g_task_new (NULL, NULL, name_callback, &name1);
|
||||||
|
g_task_set_name (t1, "some task");
|
||||||
|
g_task_return_boolean (t1, TRUE);
|
||||||
|
g_object_unref (t1);
|
||||||
|
|
||||||
|
g_main_loop_run (loop);
|
||||||
|
|
||||||
|
g_assert_cmpstr (name1, ==, "some task");
|
||||||
|
|
||||||
|
g_free (name1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
name_callback (GObject *object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
gchar **name_out = user_data;
|
||||||
|
GError *local_error = NULL;
|
||||||
|
|
||||||
|
g_assert_null (*name_out);
|
||||||
|
*name_out = g_strdup (g_task_get_name (G_TASK (result)));
|
||||||
|
|
||||||
|
g_task_propagate_boolean (G_TASK (result), &local_error);
|
||||||
|
g_assert_no_error (local_error);
|
||||||
|
|
||||||
|
g_main_loop_quit (loop);
|
||||||
|
}
|
||||||
|
|
||||||
/* test_check_cancellable: cancellation overrides return value */
|
/* test_check_cancellable: cancellation overrides return value */
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -793,6 +833,7 @@ run_in_thread_callback (GObject *object,
|
|||||||
g_assert (g_async_result_get_user_data (result) == user_data);
|
g_assert (g_async_result_get_user_data (result) == user_data);
|
||||||
g_assert (!g_task_had_error (G_TASK (result)));
|
g_assert (!g_task_had_error (G_TASK (result)));
|
||||||
g_assert_false (g_task_get_completed (G_TASK (result)));
|
g_assert_false (g_task_get_completed (G_TASK (result)));
|
||||||
|
g_assert_cmpstr (g_task_get_name (G_TASK (result)), ==, "test_run_in_thread name");
|
||||||
|
|
||||||
ret = g_task_propagate_int (G_TASK (result), &error);
|
ret = g_task_propagate_int (G_TASK (result), &error);
|
||||||
g_assert_no_error (error);
|
g_assert_no_error (error);
|
||||||
@ -816,6 +857,7 @@ run_in_thread_thread (GTask *task,
|
|||||||
g_assert (task_data == g_task_get_task_data (task));
|
g_assert (task_data == g_task_get_task_data (task));
|
||||||
g_assert (cancellable == g_task_get_cancellable (task));
|
g_assert (cancellable == g_task_get_cancellable (task));
|
||||||
g_assert_false (g_task_get_completed (task));
|
g_assert_false (g_task_get_completed (task));
|
||||||
|
g_assert_cmpstr (g_task_get_name (task), ==, "test_run_in_thread name");
|
||||||
|
|
||||||
g_assert (g_thread_self () != main_thread);
|
g_assert (g_thread_self () != main_thread);
|
||||||
|
|
||||||
@ -837,13 +879,13 @@ test_run_in_thread (void)
|
|||||||
gboolean done = FALSE;
|
gboolean done = FALSE;
|
||||||
|
|
||||||
task = g_task_new (NULL, NULL, run_in_thread_callback, &done);
|
task = g_task_new (NULL, NULL, run_in_thread_callback, &done);
|
||||||
|
g_task_set_name (task, "test_run_in_thread name");
|
||||||
g_object_weak_ref (G_OBJECT (task), task_weak_notify, (gpointer)&weak_notify_ran);
|
g_object_weak_ref (G_OBJECT (task), task_weak_notify, (gpointer)&weak_notify_ran);
|
||||||
g_signal_connect (task, "notify::completed",
|
g_signal_connect (task, "notify::completed",
|
||||||
(GCallback) completed_cb, ¬ification_emitted);
|
(GCallback) completed_cb, ¬ification_emitted);
|
||||||
|
|
||||||
g_task_set_task_data (task, (gpointer)&thread_ran, NULL);
|
g_task_set_task_data (task, (gpointer)&thread_ran, NULL);
|
||||||
g_task_run_in_thread (task, run_in_thread_thread);
|
g_task_run_in_thread (task, run_in_thread_thread);
|
||||||
g_object_unref (task);
|
|
||||||
|
|
||||||
g_mutex_lock (&run_in_thread_mutex);
|
g_mutex_lock (&run_in_thread_mutex);
|
||||||
while (!thread_ran)
|
while (!thread_ran)
|
||||||
@ -858,6 +900,10 @@ test_run_in_thread (void)
|
|||||||
g_assert (done == TRUE);
|
g_assert (done == TRUE);
|
||||||
g_assert_true (notification_emitted);
|
g_assert_true (notification_emitted);
|
||||||
|
|
||||||
|
g_assert_cmpstr (g_task_get_name (task), ==, "test_run_in_thread name");
|
||||||
|
|
||||||
|
g_object_unref (task);
|
||||||
|
|
||||||
g_mutex_lock (&run_in_thread_mutex);
|
g_mutex_lock (&run_in_thread_mutex);
|
||||||
while (!weak_notify_ran)
|
while (!weak_notify_ran)
|
||||||
g_cond_wait (&run_in_thread_cond, &run_in_thread_mutex);
|
g_cond_wait (&run_in_thread_cond, &run_in_thread_mutex);
|
||||||
@ -2139,6 +2185,7 @@ main (int argc, char **argv)
|
|||||||
g_test_add_func ("/gtask/no-callback", test_no_callback);
|
g_test_add_func ("/gtask/no-callback", test_no_callback);
|
||||||
g_test_add_func ("/gtask/report-error", test_report_error);
|
g_test_add_func ("/gtask/report-error", test_report_error);
|
||||||
g_test_add_func ("/gtask/priority", test_priority);
|
g_test_add_func ("/gtask/priority", test_priority);
|
||||||
|
g_test_add_func ("/gtask/name", test_name);
|
||||||
g_test_add_func ("/gtask/check-cancellable", test_check_cancellable);
|
g_test_add_func ("/gtask/check-cancellable", test_check_cancellable);
|
||||||
g_test_add_func ("/gtask/return-if-cancelled", test_return_if_cancelled);
|
g_test_add_func ("/gtask/return-if-cancelled", test_return_if_cancelled);
|
||||||
g_test_add_func ("/gtask/run-in-thread", test_run_in_thread);
|
g_test_add_func ("/gtask/run-in-thread", test_run_in_thread);
|
||||||
|
Loading…
Reference in New Issue
Block a user