Synchronize worker thread 41/211941/6
authorHwankyu Jhun <h.jhun@samsung.com>
Mon, 12 Aug 2019 11:11:58 +0000 (20:11 +0900)
committerHwanKyu Jhun <h.jhun@samsung.com>
Tue, 13 Aug 2019 01:17:35 +0000 (01:17 +0000)
To terminate the worker thread properly, the main thread has to wait until
the event loop of the worker thread is started. If the event loop is not
started while terminating the process, the process can be blocked.

Change-Id: I5927ca7d31e0c45d3a8783fe362147250b0e93eb
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
include/aul_worker.h
src/aul_worker.c

index bfbd0f6..ff24cd4 100644 (file)
 
 typedef void *aul_worker_h;
 
-typedef bool (*aul_worker_job_cb)(void *user_data);
-
 typedef bool (*aul_worker_io_job_cb)(int fd, void *user_data);
 
 aul_worker_h aul_worker_create(const char *name);
 
 void aul_worker_destroy(aul_worker_h handle);
 
-int aul_worker_add_idle_job(aul_worker_h handle, const char *job_name,
-               aul_worker_job_cb callback, void *user_data);
-
 int aul_worker_add_io_job(aul_worker_h handle, const char *job_name,
                int fd, aul_worker_io_job_cb callback, void *user_data);
 
index fe38233..9eb9459 100644 (file)
@@ -117,58 +117,6 @@ static int __set_comm(const char *name)
        return 0;
 }
 
-static gboolean __job_handler(gpointer data)
-{
-       struct job_s *job = (struct job_s *)data;
-       aul_worker_job_cb callback = (aul_worker_job_cb)job->callback;
-
-       if (callback(job->user_data))
-               return G_SOURCE_CONTINUE;
-
-       _I("[__JOB__] name(%s)", job->name);
-       job->tag = 0;
-
-       return G_SOURCE_REMOVE;
-}
-
-int aul_worker_add_idle_job(aul_worker_h handle, const char *job_name,
-               aul_worker_job_cb callback, void *user_data)
-{
-       struct aul_worker_s *worker = (struct aul_worker_s *)handle;
-       struct job_s *job;
-       GSource *source;
-
-       if (!worker || !job_name || !callback) {
-               _E("Invalid parameter");
-               return AUL_R_EINVAL;
-       }
-
-       source = g_idle_source_new();
-       if (!source) {
-               _E("Failed to create GSource");
-               return AUL_R_ENOMEM;
-       }
-
-       job = __create_job(job_name, NULL, callback, user_data);
-       if (!job) {
-               _E("Failed to create job(%s)", job_name);
-               g_source_unref(source);
-               return AUL_R_ENOMEM;
-       }
-
-       g_source_set_callback(source, (GSourceFunc)__job_handler, job, NULL);
-       g_source_set_priority(source, G_PRIORITY_DEFAULT);
-
-       g_mutex_lock(&worker->mutex);
-       worker->jobs = g_list_append(worker->jobs, job);
-       job->tag = g_source_attach(source, worker->context);
-       g_mutex_unlock(&worker->mutex);
-
-       g_source_unref(source);
-
-       return AUL_R_OK;
-}
-
 static gboolean __io_job_handler(GIOChannel *io, GIOCondition condition,
                gpointer data)
 {
@@ -233,15 +181,6 @@ int aul_worker_add_io_job(aul_worker_h handle, const char *job_name,
        return AUL_R_OK;
 }
 
-static bool __quit_cb(void *user_data)
-{
-       struct aul_worker_s *worker = (struct aul_worker_s *)user_data;
-
-       g_main_loop_quit(worker->loop);
-
-       return false;
-}
-
 void aul_worker_destroy(aul_worker_h handle)
 {
        struct aul_worker_s *worker = (struct aul_worker_s *)handle;
@@ -250,38 +189,68 @@ void aul_worker_destroy(aul_worker_h handle)
                return;
 
        if (worker->thread) {
-               aul_worker_add_idle_job(worker, "Quit", __quit_cb, worker);
+               g_mutex_lock(&worker->mutex);
+               if (g_main_loop_is_running(worker->loop)) {
+                       g_main_loop_quit(worker->loop);
+                       g_cond_wait(&worker->cond, &worker->mutex);
+               } else {
+                       _E("GMainLoop is not running");
+               }
+               g_mutex_unlock(&worker->mutex);
                g_thread_join(worker->thread);
        }
 
        g_cond_clear(&worker->cond);
-
-       g_mutex_lock(&worker->mutex);
-       g_mutex_unlock(&worker->mutex);
        g_mutex_clear(&worker->mutex);
 
        free(worker->name);
        free(worker);
 }
 
+static gboolean __notify_cb(gpointer data)
+{
+       struct aul_worker_s *worker = (struct aul_worker_s *)data;
+
+       _W("GMainLoop is started");
+       g_mutex_lock(&worker->mutex);
+       g_cond_signal(&worker->cond);
+       g_mutex_unlock(&worker->mutex);
+
+       return G_SOURCE_REMOVE;
+}
+
 static gpointer __worker_thread_loop(gpointer data)
 {
        struct aul_worker_s *worker = (struct aul_worker_s *)data;
+       GSource *source;
 
+       g_mutex_lock(&worker->mutex);
        __set_comm(worker->name);
 
-       g_mutex_lock(&worker->mutex);
+       source = g_idle_source_new();
+       if (!source) {
+               _E("Failed to create GSource");
+               g_cond_signal(&worker->cond);
+               g_mutex_unlock(&worker->mutex);
+               return NULL;
+       }
+
        worker->context = g_main_context_new();
        if (!worker->context) {
                _E("Failed to create GMainContext");
+               g_source_unref(source);
                g_cond_signal(&worker->cond);
                g_mutex_unlock(&worker->mutex);
                return NULL;
        }
 
+       g_source_set_callback(source, (GSourceFunc)__notify_cb, worker, NULL);
+       g_source_set_priority(source, G_PRIORITY_HIGH);
+       g_source_attach(source, worker->context);
+       g_source_unref(source);
+
        worker->loop = g_main_loop_new(worker->context, FALSE);
        g_main_context_push_thread_default(worker->context);
-       g_cond_signal(&worker->cond);
        g_mutex_unlock(&worker->mutex);
 
        if (!worker->loop) {
@@ -291,10 +260,14 @@ static gpointer __worker_thread_loop(gpointer data)
 
        g_main_loop_run(worker->loop);
 end:
+       g_mutex_lock(&worker->mutex);
        g_list_free_full(worker->jobs, __destroy_job);
        g_main_context_pop_thread_default(worker->context);
        g_main_loop_unref(worker->loop);
        g_main_context_unref(worker->context);
+       g_cond_signal(&worker->cond);
+       g_mutex_unlock(&worker->mutex);
+       _W("Shut down worker");
 
        return NULL;
 }