技术分享: glib是如何来设计跨平台的线程库的?

道哥分享
关注

2. 数据结构

你一定听说过这个公式:程序 = 数据结构 + 算法,对于一个 C 语言项目,明白了数据结构的设计,对于理解整个程序的思路是非常重要的,在 glib 中也是如此。

glib 在设计线程库的时候,分成 2 个层次:平台无关部分,平台相关部分。

平台无关的数据结构有(一些不影响理解的代码就删掉了):

struct  _GThread

 GThreadFunc func;
 gpointer data;
 gboolean joinable;
};
typedef struct _GThread GThread;
struct  _GRealThread

 GThread thread;
 gint ref_count;
 gchar *name;
};
typedef struct _GRealThread GRealThread;

平台相关的数据结构有:

Linux 系统:

typedef struct

 GRealThread thread;
 pthread_t system_thread;
 gboolean  joined;
 GMutex    lock;
 void *(*proxy) (void *);
 const GThreadSchedulerSettings *scheduler_settings;
} GThreadPosix;

Windows 系统:

typedef struct

 GRealThread thread;
 GThreadFunc proxy;
 HANDLE      handle;
} GThreadWin32;

仔细看一下每个结构体的第一个成员变量,是不是发现点什么?

从层次关系上看,这几个结构体的关系为:

Linux 平台:

Windows 平台:

结构体在内存模型中意味着什么?占据一块内存空间。

而这几个数据结构都把"子"结构体,放在"父"结构体的第一个位置,就可以方便的进行强制类型转换。

在以上内存模型中,GRealThread 结构体的第一部分是 GThread,那么就完全可以把 GRealThread 所处内存的开始部分,当做一个 GThread 结构体变量来操作。

用 C++ 中面向对象的术语来描述更准确:基类指针可以指向派生类对象。

在下面的代码中,可以看到这样的操作。

3. 线程的创建

(1) 函数原型

平台无关函数(gthread.c 中实现)

GThread *g_thread_new (const gchar *name,
             GThreadFunc  func,
             gpointer     data);
GThread *
g_thread_new_internal (const gchar *name,
                      GThreadFunc proxy,
                      GThreadFunc func,
                      gpointer data,
                      gsize stack_size,
                      const GThreadSchedulerSettings *scheduler_settings,
                      GError **error);

平台相关函数(gthread_posix.c or ghread_win32.c 中实现)

GRealThread *
g_system_thread_new (GThreadFunc proxy,
                    gulong stack_size,
                    const GThreadSchedulerSettings *scheduler_settings,
                    const char *name,
                    GThreadFunc func,
                    gpointer data,
                    GError **error);

声明: 本文由入驻OFweek维科号的作者撰写,观点仅代表作者本人,不代表OFweek立场。如有侵权或其他问题,请联系举报。
侵权投诉

下载OFweek,一手掌握高科技全行业资讯

还不是OFweek会员,马上注册
打开app,查看更多精彩资讯 >
  • 长按识别二维码
  • 进入OFweek阅读全文
长按图片进行保存