做跨平台开发的时候有时需要使用到线程库,但是不同平台的线程库是不一样的,在Windows上是使用系统win32 api创建和管理线程,Linux和Mac通常使用pthread,尽管Windows也可以使用第三方的pthread库,但这样库的依赖会比较多,项目的部署会麻烦些,最佳的方法应该还是写跨平台代码,通过宏区分不同平台的代码。
一、接口设计:
比较常用的线程相关的功能通常有:
1、线程对象
用这种方式定义线程对象是为了隐藏内部实现,减少头文件的依赖,方便跨平台实现。
typedef void* acf_thread;
2、创建线程
创建线程,传入函数指针及自定义数据,调用后线程会立刻启动。
typedef void(*acf_thread_callback)(void* userdata);
acf_thread acf_thread_create( acf_thread_callback callback, void*userdata);
3、等待线程
等待线程退出,并且退出后销毁线程对象。
void acf_thread_wait_destroy(acf_thread thread);
4、销毁线程对象
销毁线程对象,但线程仍然继续运行。
void acf_thread_detach_destroy(acf_thread thread);
5、睡眠
延时,参数单位毫秒。
void acf_thread_sleep(int millisecond);
6、获取当前线程id
uintptr_t acf_thread_self_id();
二、关键实现:
1、睡眠
在Windows平台直接调用Sleep即可,但是Linux和Mac没有直接的sleep方法,用select替代实现:
void acf_thread_sleep(int millisecond) {
#ifdef _WIN32
Sleep(millisecond);
#else
struct timespec delay = { millisecond/1000 ,(millisecond%1000) * 1000 };
select(NULL, NULL, NULL, NULL, &delay);
#endif
}
2、获取线程Id
在Windows平台有GetCurrentThreadId函数获取线程Id,Linux和Mac需要使用pthead的pthread_self函数:
uintptr_t acf_thread_self_id()
{
#ifdef _WIN32
return GetCurrentThreadId();
#else
return (uintptr_t)pthread_self();
#endif
}
三、使用例子:
#include"Thread/acf_thread.h"
#include<stdio.h>
static void fun(void* arg) {
if (sizeof(uintptr_t) == 8)
printf("thread %d created tid=%llu\n", (int)arg, acf_thread_self_id());
else
printf("thread %d created tid=%u\n", (int)arg, acf_thread_self_id());
acf_thread_sleep(3000);
printf("thread %d exit\n", (int)arg);
}
int main(int argc, char** argv) {
//打印主线程Id
printf("main thread tid=%d\n", acf_thread_self_id());
//创建线程1
acf_thread thead1 = acf_thread_create(fun, 1);
//创建线程2
acf_thread thead2 = acf_thread_create(fun, 2);
//分离线程1并销毁对象
acf_thread_detach_destroy(thead1);
printf("detached destroied thread 1\n");
printf("wait for thread 2\n");
//等待线程2退出
acf_thread_wait_destroy(thead2);
printf("destroied thread 2");
return 0;
}
四、完整代码: