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,头文件拷贝到项目就能直接用。

相关推荐
蜀道山老天师8 分钟前
Shell Bash变量与运算符(含条件测试与流程控制)
linux·运维·bash
Mr.朱鹏16 分钟前
Linux 服务器 LVM 根分区在线动态扩容
linux·服务器·数据库
mengge.cloud29 分钟前
存储技术基础小白教程
linux·运维·服务器·wpf·存储
霸道流氓气质34 分钟前
Spring AI 输出解析器进阶
人工智能·windows·spring
tang777891 小时前
反爬虫场景下代理IP池的动态扩容与失效IP自动清理方案实现
linux·服务器·网络·爬虫代理·住宅代理ip
新时代牛马2 小时前
Linux 系统调用与IPC 完整篇:从syscall 入口、VDSO 到pipe/shm/futex 选型
linux·运维·服务器
黄一一9112433 小时前
跨平台视频图片压缩互转!离线视频压缩工具!Github开源轻松无损压缩视频!Win/Mac/Linux三端通用开源工具
windows·macos·音视频·开源软件
fpcc4 小时前
计算机原理—Linux是如何加载可执行文件到内存
linux
野熊佩骑4 小时前
Kubernetes实战系列文章(三) 之 K8S运维常用命令
linux·运维·docker·微服务·云原生·容器·kubernetes
码农客栈4 小时前
linux 设备树下的 platform 驱动编写
linux