c语言 封装跨平台线程头文件

c语言线程类

第一章 跨平台线程


文章目录


前言

c语言的标准库是没有线程类的,不同平台的使用方式都有所不同,Windows上通常用win32 api,其他平台则是pthread。当想要写通用的跨平台代码时,涉及到多线程操作就会很不方便。笔者以前写过跨平台线程类的封装,自定义了一套接口和实现,能使用但是还不是最方便的。比如写项目的时候还是需要在cmakelist中加入.c文件的。本文的做法是进一步简化,只需要一个头文件就能实现跨平台的线程封装。


一、如何实现?

我们其实只需要通过宏定义一套接口就可以了,而不需要自定义线程对象以及函数和实现。

定义一个宏方法在Windows上宏展开是调用win32 api,其他平台则是调用pthread。

如下:

cpp 复制代码
#ifdef _WIN32
#include <windows.h>
/**
 * @brief 创建线程
 * @param thread 线程句柄,类型为Thread*
 * @param callback 回调方法,格式:TINT thread_callback(void* arg);  thread_callback中的返回类型是整型int,不同平台长度不同所以只能统一为int。
 * @param arg 回调参数,类型为void*
 * @return 0成功,其他值失败
 */
#define thread_create(thread, callback, arg) (*(thread) = CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)callback,arg, 0, NULL))==0
#else
#include <pthread.h>
#define thread_create(tid, callback, arg) pthread_create(tid, NULL, (void*(*)(void*))callback, arg)
#endif

二、完整代码

thread.h

c 复制代码
/************************************************************************************************************************
 * Copyright (C): 2025-2025, codeofcc. All rights reserved.
 * @file : thread.h
 * @brief : 通用线程类封装,在Windows上使用win32api,其他平台使用pthread。
 * @author : codeofcc
 * @email : 
 * @version : 1.0.0
 * @date : 2025/6/6 16:34:27
******************************************************************************************************************/
#ifndef THREAD_H
#define THREAD_H
#ifdef _WIN32
#ifndef _WIN32_WINNT
//使用mingw编译时需要此定义。
#define _WIN32_WINNT 0x0600
#endif
#include <windows.h>
#include <synchapi.h>
/// @brief 线程句柄
typedef HANDLE Thread;
/// @brief 线程回调的返回定义,仅作为函数定义,不能作为类型。
#define TINT int WINAPI
/**
 * @brief 创建线程
 * @param thread 线程句柄,类型为Thread*
 * @param callback 回调方法,格式:TINT thread_callback(void* arg);  thread_callback中的返回类型是整型int,不同平台长度不同所以只能统一为int。
 * @param arg 回调参数,类型为void*
 * @return 0成功,其他值失败
 */
#define thread_create(thread, callback, arg) (*(thread) = CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)callback,arg, 0, NULL))==0
/**
 * @brief 等待线程结束,结束后会销毁线程句柄
 * @param thread 线程句柄,类型为Thread
 * @param ret 返回值,类型未int*
 * @return 0成功,其他值失败
 */
#define thread_join(thread,ret) WaitForSingleObject(thread, INFINITE); if(ret)GetExitCodeThread(thread,(LPDWORD) ret);CloseHandle(thread)
/**
 * @brief 分离线程,会销毁线程句柄,但线程依然执行
 * @param thread 线程句柄,类型为Thread
 * @return 0成功,其他值失败
 */
#define thread_detach(thread) CloseHandle(thread)==0
/**
 * @brief 获取当前线程id
 * @return 线程id,类型为unsigned long
 */
#define thread_self_id() (unsigned long)GetCurrentThreadId()
/**
 * @brief 休眠当前线程
 * @param ms 毫秒数
 * @return void无返回
 */
#define thread_sleep(ms) Sleep(ms)
#else
#include <pthread.h>
#include <sys/time.h>
#include <semaphore.h>
#include <stdint.h>
typedef pthread_t Thread;
#define TINT intptr_t
#define thread_create(tid, callback, arg) pthread_create(tid, NULL, (void*(*)(void*))callback, arg)
#define thread_join(tid,ret) { intptr_t retval;  pthread_join(tid, (void**)&retval); if (ret){*(int*)ret = (int)retval; } }
#define thread_detach(tid) pthread_detach(tid)
#define thread_self_id() (unsigned long)pthread_self()
#define thread_sleep(ms){struct timeval delay = {ms / 1000, (ms % 1000) * 1000}; select(NULL, NULL, NULL, NULL, &delay);}      
#endif
#endif

三、使用示例

1、创建线程并等待返回

c 复制代码
#include"thread.h"
#include<stdint.h>
TINT thread_proc(void *arg)
{
	intptr_t num = (intptr_t)arg;
    printf("pass arg : %d , thread id : %d\n", (int)num,thread_self_id());
	//sleep200毫秒
	thread_sleep(200);
	// 返回线程id
	return thread_self_id();
}

int main()
{
    //线程句柄
	Thread thread;
	int ret;
	// 创建线程
	thread_create(&thread, thread_proc, (void *)1);
	// 等待线程结束,并获取返回值
	thread_join(thread, &ret);
	printf("return thread id : %d \n",ret);
	return 0;
}

2、创建线程并分离

c 复制代码
#include"thread.h"
#include<stdint.h>
TINT thread_proc(void *arg)
{
	intptr_t num = (intptr_t)arg;
    printf("pass arg : %d , thread id : %d\n", (int)num,thread_self_id());
	//sleep200毫秒
	thread_sleep(200);
    printf("thread exit\n");
	return 0;
}

int main()
{
    //线程句柄
	Thread thread;
	int ret;
	//创建线程
	thread_create(&thread, thread_proc, (void *)1);
	//分离线程
	thread_detach(thread);
    printf("detach thread \n");
	thread_sleep(1000);
	printf("program exit\n");
	return 0;
}

总结

以上就是今天要讲的内容,本文只是简单不同平台的线程方法进行了一个整合,对函数的参数和返回值做了一个统一,由于在所有实现在头文件中,使用起来是很方便的,不需要额外编写makefile或cmakelist,头文件拷贝到项目就能直接用。

相关推荐
coder_lorraine6 分钟前
【Linux系列】Linux用户大揭秘:从“公寓住户”到“社区管理员”的奇幻之旅
linux
藥瓿锻37 分钟前
2024 CKA题库+详尽解析| 15、备份还原Etcd
linux·运维·数据库·docker·容器·kubernetes·cka
bbsh20991 小时前
WebFuture:Ubuntu 系统上在线安装.NET Core 8 的步骤
linux·ubuntu·.netcore·webfuture
ZZZKKKRTSAE1 小时前
快速上手Linux全局搜索正则表达式(grep)
linux·服务器·正则表达式
waving-black2 小时前
利用frp和腾讯云服务器将内网暴露至外网(内网穿透)
linux·服务器·腾讯云·frp·内网穿透
stormsha2 小时前
Linux中su与sudo命令的区别:权限管理的关键差异解析
linux·运维·服务器·鸿蒙系统·ux·batch命令
草莓熊Lotso2 小时前
【数据结构初阶】--算法复杂度的深度解析
c语言·开发语言·数据结构·经验分享·笔记·其他·算法
KyollBM3 小时前
【CF】Day75——CF (Div. 2) B (数学 + 贪心) + CF 882 (Div. 2) C (01Trie | 区间最大异或和)
c语言·c++·算法
筏.k3 小时前
grep、wc 与管道符快速上手指南
linux
Johny_Zhao3 小时前
华为MAAS、阿里云PAI、亚马逊AWS SageMaker、微软Azure ML各大模型深度分析对比
linux·人工智能·ai·信息安全·云计算·系统运维