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