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;
};
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);
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);
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