From: Joonbum Ko Date: Wed, 16 Nov 2022 08:21:08 +0000 (+0900) Subject: utils_gthread: Add new functions to pause/continue thread X-Git-Tag: accepted/tizen/unified/20221206.170553~9 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b95029e498082dd8baf49d55213c9557155a196b;p=platform%2Fcore%2Fuifw%2Flibtpl-egl.git utils_gthread: Add new functions to pause/continue thread tpl_gthread_wait_idle - Create a new idle source and attach it to thread context. This function will be blocked until idle callback is called. If the thread has some worksto be handled, wait for the thread to finish it. tpl_gthread_pause_in_idle - Pause the thread when idle callback is called. tpl_gthread_continue - Continue the paused thread. Change-Id: I5a2aaf3b8b9579306246234d252b643b6cc0bf3e Signed-off-by: Joonbum Ko --- diff --git a/src/tpl_utils_gthread.c b/src/tpl_utils_gthread.c index f1dab0c..500507f 100644 --- a/src/tpl_utils_gthread.c +++ b/src/tpl_utils_gthread.c @@ -7,6 +7,12 @@ struct _tpl_gthread { GMutex thread_mutex; GCond thread_cond; + GMutex idle_mutex; + GCond idle_cond; + GMutex pause_mutex; + tpl_bool_t is_idle; + tpl_bool_t paused; + tpl_gthread_func init_func; void *func_data; }; @@ -86,6 +92,12 @@ tpl_gthread_create(const char *thread_name, g_mutex_init(&new_thread->thread_mutex); g_cond_init(&new_thread->thread_cond); + g_mutex_init(&new_thread->pause_mutex); + g_mutex_init(&new_thread->idle_mutex); + g_cond_init(&new_thread->idle_cond); + + new_thread->is_idle = TPL_FALSE; + new_thread->paused = TPL_FALSE; g_mutex_lock(&new_thread->thread_mutex); @@ -115,6 +127,10 @@ tpl_gthread_destroy(tpl_gthread *thread) g_mutex_unlock(&thread->thread_mutex); + g_mutex_clear(&thread->pause_mutex); + g_mutex_clear(&thread->idle_mutex); + g_cond_clear(&thread->idle_cond); + g_mutex_clear(&thread->thread_mutex); g_cond_clear(&thread->thread_cond); @@ -448,4 +464,77 @@ void tpl_gcond_signal(tpl_gcond *gcond) { g_cond_signal(gcond); +} + +static gboolean +_thread_idle_cb(gpointer data) +{ + tpl_gthread *gthread = (tpl_gthread *)data; + + TPL_DEBUG("THREAD IDLE CALLBACK"); + + g_mutex_lock(>hread->idle_mutex); + gthread->is_idle = TPL_TRUE; + g_cond_signal(>hread->idle_cond); + g_mutex_unlock(>hread->idle_mutex); + + /* If the caller thread of tpl_gthread_wait_idle locked the pause_mutex, + * thread will be paused here until unlock */ + g_mutex_lock(>hread->pause_mutex); + g_mutex_unlock(>hread->pause_mutex); + + return G_SOURCE_REMOVE; +} + +void +tpl_gthread_wait_idle(tpl_gthread *gthread) +{ + TPL_CHECK_ON_NULL_RETURN(gthread); + + GSource *idle_source = NULL; + + TPL_DEBUG("[WAIT IDLE] BEGIN"); + + g_mutex_lock(>hread->idle_mutex); + gthread->is_idle = TPL_FALSE; + + idle_source = g_idle_source_new(); + if (idle_source == NULL) { + TPL_WARN("Failed to create and attach idle source"); + g_mutex_unlock(>hread->idle_mutex); + return; + } + + g_source_set_priority(idle_source, G_PRIORITY_LOW); + g_source_set_callback(idle_source, + _thread_idle_cb, (gpointer)gthread, + NULL); + g_source_attach(idle_source, g_main_loop_get_context(gthread->loop)); + g_source_unref(idle_source); + + while (!gthread->is_idle) { + g_cond_wait(>hread->idle_cond, >hread->idle_mutex); + } + g_mutex_unlock(>hread->idle_mutex); + + TPL_DEBUG("[WAIT IDLE] END"); +} + +void +tpl_gthread_pause_in_idle(tpl_gthread *gthread) +{ + TPL_CHECK_ON_NULL_RETURN(gthread); + + g_mutex_lock(>hread->pause_mutex); + tpl_gthread_wait_idle(gthread); + gthread->paused = TPL_TRUE; +} + +void +tpl_gthread_continue(tpl_gthread *gthread) +{ + TPL_CHECK_ON_NULL_RETURN(gthread); + + if (!gthread->paused) return; + g_mutex_unlock(>hread->pause_mutex); } \ No newline at end of file diff --git a/src/tpl_utils_gthread.h b/src/tpl_utils_gthread.h index 8185cab..66552c4 100644 --- a/src/tpl_utils_gthread.h +++ b/src/tpl_utils_gthread.h @@ -201,6 +201,29 @@ tpl_gcond_timed_wait(tpl_gcond *gcond, tpl_gmutex *gmutex, int64_t timeout_ms); void tpl_gcond_signal(tpl_gcond *gcond); +/** + * attach idle source and waiting for idle callback + * + * @param gthread Pointer to tpl_gthread + */ +void +tpl_gthread_wait_idle(tpl_gthread *gthread); + +/** + * pause thread when idle callback is called + * + * @param gthread Pointer to tpl_gthread + */ +void +tpl_gthread_pause_in_idle(tpl_gthread *gthread); + +/** + * continue thread if thread was paused + * + * @param gthread Pointer to tpl_gthread + */ +void +tpl_gthread_continue(tpl_gthread *gthread);