c语言 封装跨平台条件变量头文件

c语言线程类

第一章 跨平台线程
第二章 跨平台互斥锁
第三章 跨平台信号量
第四章 跨平台条件变量(本章)
第五章 跨平台读写锁
第六章 整合版


文章目录


前言

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


一、如何实现?

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

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

如下:

cpp 复制代码
#ifdef _WIN32
#ifndef _WIN32_WINNT
//使用mingw编译时需要此定义。
#define _WIN32_WINNT 0x0600
#endif
#include <windows.h>
/// @brief 条件变量
typedef CONDITION_VARIABLE Cond;
/**
 * @brief 创建条件变量
 * @param cond 条件变量,类型为Cond*
 * @return 0成功,其他值失败
 */
#define cond_create(cond) 1==0,InitializeConditionVariable(cond)
#else
#include <pthread.h>
#include <sys/time.h>
#include <stdint.h>
typedef pthread_cond_t Cond;
#define cond_create(cond) pthread_cond_init(cond,0)
#endif

二、完整代码

cond.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 COND_H
#define COND_H
#ifdef _WIN32
#ifndef _WIN32_WINNT
//使用mingw编译时需要此定义。
#define _WIN32_WINNT 0x0600
#endif
#include <windows.h>
/// @brief 条件变量
typedef CONDITION_VARIABLE Cond;
/**
 * @brief 创建条件变量
 * @param cond 条件变量,类型为Cond*
 * @return 0成功,其他值失败
 */
#define cond_create(cond) 1==0,InitializeConditionVariable(cond)
/**
 * @brief 销毁条件变量
 * @param cond 条件变量,类型为Cond*
 * @return void无返回
 */
#define cond_destroy(cond) WakeAllConditionVariable(cond)
/**
 * @brief 等待条件变量
 * @param cond 条件变量,类型为Cond*
 * @param mtx 互斥变量,类型为Mutex*
 * @return 0成功,其他值失败
 */
#define cond_wait(cond, mtx) SleepConditionVariableCS(cond, mtx, INFINITE)==0
/**
 * @brief 等待条件变量,带超时时间
 * @param cond 条件变量,类型为Cond*
 * @param mtx 互斥变量,类型为Mutex*
 * @param ms 超时时间,相对时间,单位毫秒,类型为int
 * @param ret 返回值,0成功,其他值失败。类型为int*
 * @return void无返回
 */
#define cond_wait_time(cond, mtx,ms,ret) *(ret)=SleepConditionVariableCS(cond, mtx, ms)==0
/**
 * @brief 释放条件变量
 * @param cond 条件变量,类型为Cond*
 * @return void无返回
 */
#define cond_post(cond) WakeConditionVariable(cond)
/**
 * @brief 释放条件变量,广播
 * @param cond 条件变量,类型为Cond*
 * @return void无返回
 */
#define cond_brocast(cond) WakeAllConditionVariable(cond)
#else
#include <pthread.h>
#include <sys/time.h>
#include <stdint.h>
typedef pthread_cond_t Cond;
#define cond_create(cond) pthread_cond_init(cond,0)
#define cond_destroy(cond) pthread_cond_destroy(cond)
#define cond_wait(cond, mtx) pthread_cond_wait(cond, mtx)
#define cond_wait_time(cond, mtx,ms,ret)  { struct timespec time;clock_gettime(CLOCK_REALTIME, &time); time.tv_sec += (ms / 1000);time.tv_nsec+=((ms % 1000)) * 1000000; *(ret)=pthread_cond_timedwait(cond, mtx,&time);}
#define cond_post(cond) pthread_cond_signal(cond)
#define cond_brocast(cond) pthread_cond_broadcast(cond)
#endif
#endif

三、使用示例

1、多线程等待

c 复制代码
 #include "cond.h"
TINT task(void *arg)
{
	Cond *cond = (Cond *)arg;
	//执行任务
	thread_sleep(500);
	//完成后通知
	cond_post(cond);
	return 0;
}

int main()
{
	int ret = 0;
	Cond cond;
	Mutex mtx;
	mutex_create(&mtx);
	ret = cond_create(&cond);
	if (ret != 0)
	{
		printf("cond_create error %d\n", ret);
		return -1;
	}
	//开启线程
	Thread thread;
	thread_create(&thread, task, (void *)&cond);
	thread_detach(thread);
	//等待任务
	mutex_lock(&mtx);
	cond_wait(&cond, &mtx);
	mutex_unlock(&mtx);
	//结束后销毁资源
	mutex_destroy(&mtx);
	cond_destroy(&cond);
}

2、超时等待

c 复制代码
#include "cond.h"
TINT task(void *arg)
{
	Cond *cond = (Cond *)arg;
	// 执行任务
	thread_sleep(500);
	// 完成后通知
	cond_post(cond);
	return 0;
}

int main()
{
	int ret = 0;
	Cond cond;
	Mutex mtx;
	mutex_create(&mtx);
	ret = cond_create(&cond);
	if (ret != 0)
	{
		printf("cond_create error %d\n", ret);
		return -1;
	}
	// 开启线程
	Thread thread;
	thread_create(&thread, task, (void *)&cond);
	thread_detach(thread);
	do
	{
		//执行其他操作避免阻塞
         ...
		// 等待任务,超时30毫秒
		mutex_lock(&mtx);
		cond_wait_time(&cond, &mtx, 30, &ret);
		mutex_unlock(&mtx);
	} while (!ret);
	// 结束后销毁资源
	mutex_destroy(&mtx);
	cond_destroy(&cond);
}

总结

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

相关推荐
_Voosk2 小时前
macOS Xcode C++程序设置相对路径根目录
c语言·c++·xcode·swift
小刘爱玩单片机2 小时前
【stm32简单外设篇】- LCD1602A
c语言·stm32·单片机·嵌入式硬件
巧克力味的桃子3 小时前
让程序在读取到整数0时就终止循环
c语言·算法
C++ 老炮儿的技术栈3 小时前
时序数据库 相对于关系型数据库,有什么区别
c语言·开发语言·c++·机器人·时序数据库·visual studio
k***92164 小时前
C语言模拟面向对象三大特性与C++实现对比
java·c语言·c++
黎雁·泠崖4 小时前
C 语言预处理(下):宏与函数对比 +#/## 运算符 + 条件编译 + 头文件包含
c语言·开发语言
代码游侠4 小时前
应用——SQLite3 C 编程学习
linux·服务器·c语言·数据库·笔记·网络协议·sqlite
无言(* ̄(エ) ̄)4 小时前
C语言--运算符/函数/结构体/指针
c语言·开发语言·数据结构·数据库·算法·mongodb
Tipriest_4 小时前
Linux 下开发 C/C++ 程序为什么头文件引用路径这么多和复杂
linux·c语言·c++