utils_gthread: Add new functions to pause/continue thread 12/284512/1
authorJoonbum Ko <joonbum.ko@samsung.com>
Wed, 16 Nov 2022 08:21:08 +0000 (17:21 +0900)
committerJoonbum Ko <joonbum.ko@samsung.com>
Fri, 18 Nov 2022 08:40:58 +0000 (17:40 +0900)
 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 <joonbum.ko@samsung.com>
src/tpl_utils_gthread.c
src/tpl_utils_gthread.h

index f1dab0c..500507f 100644 (file)
@@ -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(&gthread->idle_mutex);
+       gthread->is_idle = TPL_TRUE;
+       g_cond_signal(&gthread->idle_cond);
+       g_mutex_unlock(&gthread->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(&gthread->pause_mutex);
+       g_mutex_unlock(&gthread->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(&gthread->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(&gthread->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(&gthread->idle_cond, &gthread->idle_mutex);
+       }
+       g_mutex_unlock(&gthread->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(&gthread->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(&gthread->pause_mutex);
 }
\ No newline at end of file
index 8185cab..66552c4 100644 (file)
@@ -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);