Skip to content

Instantly share code, notes, and snippets.

@lidaobing
Created July 8, 2026 03:03
Show Gist options
  • Select an option

  • Save lidaobing/fb2efd54552aafeadc4b5effc61364d5 to your computer and use it in GitHub Desktop.

Select an option

Save lidaobing/fb2efd54552aafeadc4b5effc61364d5 to your computer and use it in GitHub Desktop.
#include <gio/gio.h>
#include <glib.h>
#include <stdint.h>
#include <stdatomic.h>
// ============================================================================
// 1. 宏定义与核心工具 (Macros & Utilities)
// ============================================================================
// 仿 RAII 自动加解锁宏
#define WITH_MUTEX_LOCK(mutex) \
for (gboolean _lock_done = (g_mutex_lock(&(mutex)), TRUE); \
_lock_done; \
g_mutex_unlock(&(mutex)), _lock_done = FALSE)
// 线程所有权断言宏
#ifdef G_ENABLE_DEBUG
#define ASSERT_IN_BUSINESS_THREAD() g_assert_true (g_main_context_is_owner (business_context))
#define ASSERT_IN_UI_THREAD() g_assert_true (g_main_context_is_owner (NULL))
#else
#define ASSERT_IN_BUSINESS_THREAD() ((void)0)
#define ASSERT_IN_UI_THREAD() ((void)0)
#endif
// 模拟国际化宏(如果实际项目中没有 gettext,通常这样 fallback)
#ifndef _
#define _(String) (String)
#endif
// ============================================================================
// 2. 业务任务抽象层 (Business Task Abstraction)
// ============================================================================
typedef struct _BusinessTask BusinessTask;
typedef void (*BusinessTaskCallback) (BusinessTask *b_task,
gpointer result_data,
GError *error,
gpointer user_data);
typedef struct {
gboolean (*start) (BusinessTask *b_task, GError **error);
void (*finalize) (BusinessTask *b_task);
} BusinessTaskOps;
struct _BusinessTask {
const BusinessTaskOps *ops;
gpointer user_data;
BusinessTaskCallback completion_callback;
gpointer callback_user_data;
};
// ============================================================================
// 3. 具体业务实现:下载任务 (Concrete Task: Download)
// ============================================================================
typedef struct {
gchar *url;
} DownloadPrivate;
static void
on_download_async_ready (GObject *source, GAsyncResult *res, gpointer user_data)
{
BusinessTask *b_task = (BusinessTask *)user_data;
DownloadPrivate *priv = (DownloadPrivate *)b_task->user_data;
// 此时绝对在业务线程执行
ASSERT_IN_BUSINESS_THREAD();
gchar *downloaded_content = g_strdup ("<html>Content From Server</html>");
if (b_task->completion_callback) {
b_task->completion_callback (b_task, downloaded_content, NULL, b_task->callback_user_data);
}
b_task->ops->finalize (b_task);
g_free (b_task);
}
static gboolean
download_task_start (BusinessTask *b_task, GError **error)
{
ASSERT_IN_BUSINESS_THREAD();
DownloadPrivate *priv = (DownloadPrivate *)b_task->user_data;
if (!priv->url || strlen(priv->url) == 0) {
// I18N 友好的错误定义
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("URL can not be empty."));
return FALSE;
}
// 模拟挂载一个非阻塞的异步 I/O (2秒后触发)
g_timeout_add (2000, (GSourceFunc)on_download_async_ready, b_task);
return TRUE;
}
static void
download_task_finalize (BusinessTask *b_task)
{
DownloadPrivate *priv = (DownloadPrivate *)b_task->user_data;
g_free (priv->url);
g_free (priv);
}
static const BusinessTaskOps download_ops = {
.start = download_task_start,
.finalize = download_task_finalize
};
BusinessTask *
download_task_new (const gchar *url)
{
BusinessTask *b_task = g_new0 (BusinessTask, 1);
b_task->ops = &download_ops;
DownloadPrivate *priv = g_new0 (DownloadPrivate, 1);
priv->url = g_strdup (url);
b_task->user_data = priv;
return b_task;
}
// ============================================================================
// 4. 业务群调度层 (Scheduler Layer)
// ============================================================================
static GMainContext *business_context = NULL;
static GThread *business_thread = NULL;
static GMutex init_mutex;
static GCond init_cond;
static gboolean is_initialized = FALSE;
static void
scheduler_on_task_completed (BusinessTask *b_task, gpointer result_data, GError *error, gpointer user_data)
{
ASSERT_IN_BUSINESS_THREAD();
GTask *g_task = G_TASK (user_data);
if (error) {
g_task_return_error (g_task, g_error_copy (error));
} else {
// 使用 g_free 作为销毁通知,GTask 会自动在 UI 线程释放 result_data 内存
g_task_return_pointer (g_task, result_data, g_free);
}
g_object_unref (g_task);
}
static gboolean
scheduler_process_task (gpointer user_data)
{
ASSERT_IN_BUSINESS_THREAD();
gpointer *pair = (gpointer *)user_data;
BusinessTask *b_task = (BusinessTask *)pair[0];
GTask *g_task = (GTask *)pair[1];
g_free (pair);
GError *error = NULL;
b_task->completion_callback = scheduler_on_task_completed;
b_task->callback_user_data = g_task;
if (!b_task->ops->start (b_task, &error)) {
g_task_return_error (g_task, error);
g_object_unref (g_task);
if (b_task->ops->finalize) b_task->ops->finalize (b_task);
g_free (b_task);
}
return G_SOURCE_REMOVE;
}
static gpointer
business_thread_func (gpointer data)
{
GMainContext *context = g_main_context_new ();
g_main_context_push_thread_default (context);
GMainLoop *loop = g_main_loop_new (context, FALSE);
g_mutex_lock (&init_mutex);
business_context = context;
is_initialized = TRUE;
g_cond_signal (&init_cond);
g_mutex_unlock (&init_mutex);
g_main_loop_run (loop);
g_main_loop_unref (loop);
g_main_context_pop_thread_default (context);
g_main_context_unref (context);
return NULL;
}
void
business_thread_init (void)
{
g_mutex_init (&init_mutex);
g_cond_init (&init_cond);
g_mutex_lock (&init_mutex);
business_thread = g_thread_new ("business-worker", business_thread_func, NULL);
while (!is_initialized) {
g_cond_wait (&init_cond, &init_mutex);
}
g_mutex_unlock (&init_mutex);
}
// ============================================================================
// 5. UI 监视层与管道门槛 (UI Monitor & Pipeline Launcher)
// ============================================================================
static GList *active_tasks_list = NULL;
static GMutex active_tasks_mutex;
static atomic_uint_fast64_t global_task_id_counter = 0;
typedef struct {
guint64 task_id;
gchar *description;
gint64 start_time;
} UITaskTracker;
static void
on_ui_task_tracker_destroy (gpointer data)
{
// 注意:GTask 销毁通知通常在 UI 线程执行
UITaskTracker *tracker = (UITaskTracker *)data;
WITH_MUTEX_LOCK (active_tasks_mutex) {
active_tasks_list = g_list_remove (active_tasks_list, tracker);
}
gint64 duration = (g_get_monotonic_time () - tracker->start_time) / 1000;
// I18N 友好 且 视觉清爽的 %jd 现代化打印
g_print (_("[UI Log] 🔴 Task Finished | ID: %jd | Desc: %s | Latency: %jd ms\n"),
(intmax_t)tracker->task_id, tracker->description, (intmax_t)duration);
g_free (tracker->description);
g_free (tracker);
}
void
ui_task_pipeline_launch (BusinessTask *b_task, const gchar *description, GAsyncReadyCallback callback, gpointer user_data)
{
ASSERT_IN_UI_THREAD();
GTask *g_task = g_task_new (NULL, NULL, callback, user_data);
UITaskTracker *tracker = g_new0 (UITaskTracker, 1);
// C11 原子无锁自增
tracker->task_id = atomic_fetch_add (&global_task_id_counter, 1) + 1;
tracker->description = g_strdup (description);
tracker->start_time = g_get_monotonic_time ();
g_task_set_task_data (g_task, tracker, on_ui_task_tracker_destroy);
WITH_MUTEX_LOCK (active_tasks_mutex) {
active_tasks_list = g_list_append (active_tasks_list, tracker);
}
g_print (_("[UI Log] 🟢 Task Launched | ID: %jd | Desc: %s\n"),
(intmax_t)tracker->task_id, tracker->description);
gpointer *pair = g_new (gpointer, 2);
pair[0] = b_task;
pair[1] = g_task;
g_main_context_invoke (business_context, scheduler_process_task, pair);
}
// ============================================================================
// 6. 应用程序上层入口测试 (Main Entry & Test)
// ============================================================================
static void
on_my_download_completed (GObject *source, GAsyncResult *res, gpointer user_data)
{
ASSERT_IN_UI_THREAD();
GError *error = NULL;
// 从 GTask 中取出被包裹的返回指针
gchar *content = (gchar *)g_task_propagate_pointer (G_TASK (res), &error);
if (error) {
g_printerr (_("[UI View] Error occurred: %s\n"), error->message);
g_clear_error (&error);
} else {
g_print (_("[UI View] Successfully rendered UI with data: %s\n"), content);
g_free (content); // 释放上层拿到的指针
}
// 测试完毕,退出主循环
GMainLoop *ui_loop = (GMainLoop *)user_data;
g_main_loop_quit (ui_loop);
}
int
main (int argc, char *argv[])
{
g_mutex_init (&active_tasks_mutex);
// 1. 初始化后台业务线程
business_thread_init ();
// 2. 创建主 UI 线程的 MainLoop
GMainLoop *ui_loop = g_main_loop_new (NULL, FALSE);
g_print ("[Main] App started. Simulating button click...\n");
// 3. 构建业务子类对象
BusinessTask *download_job = download_task_new ("https://api.example.com/data");
// 4. 通过管道发射任务
ui_task_pipeline_launch (download_job, "Download System Data", on_my_download_completed, ui_loop);
// 5. 启动 UI 主循环
g_main_loop_run (ui_loop);
// 6. 清理退出
g_main_loop_unref (ui_loop);
g_mutex_clear (&active_tasks_mutex);
g_mutex_clear (&init_mutex);
g_cond_clear (&init_cond);
g_print ("[Main] App exited cleanly.\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment