头文件:
#include <stdbool.h>
// 句柄
typedef void* EventHandle;
// 创建实例
EventHandle stCreateEvent(bool initState, bool manualReset);
// 释放实例
void stReleaseEvent(EventHandle handle);
// 等待事件。有信号返回true,否则false。无限等待时 waitTime_ms 置 0xffffffff。
bool stWaitEvent(EventHandle handle, unsigned int waitTime_ms);
// 重置事件为无信号
void stResetEvent(EventHandle handle);
// 事件设为有信号
void stSetEvent(EventHandle handle);
实现:
#include "cEvent.h" // 这是头文件名字
#include <pthread.h>
#include <sys/time.h>
#include <errno.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
typedef struct {
bool m_state; // true : 有信号; false : 无信号
bool m_manualReset;
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
} st_Event_Info;
EventHandle stCreateEvent(bool initState, bool manualReset)
{
st_Event_Info* p = (st_Event_Info*)malloc(sizeof(st_Event_Info));
if (p) {
p->m_state = initState;
p->m_manualReset = manualReset;
pthread_mutex_init(&p->m_mutex, NULL);
pthread_cond_init(&p->m_cond, NULL);
}
return p;
}
void stReleaseEvent(EventHandle handle)
{
if (handle) {
st_Event_Info* p = (st_Event_Info*)handle;
// pthread_mutex_lock(&p->m_mutex);
// p->m_state = false;
// // 如果有等待中的,则激活全部
// pthread_cond_broadcast(&p->m_cond);
// pthread_mutex_unlock(&p->m_mutex);
pthread_mutex_destroy(&p->m_mutex);
while (EBUSY == pthread_cond_destroy(&p->m_cond)) {
assert(0);
usleep(10);
}
free(handle);
}
}
bool stWaitEvent(EventHandle handle, unsigned int waitTime_ms)
{
bool ret = true;
st_Event_Info* p = (st_Event_Info*)handle;
int waitRet = 0;
if (handle) {
pthread_mutex_lock(&p->m_mutex);
if (p->m_state) {
if (!p->m_manualReset)
p->m_state = false;
pthread_mutex_unlock(&p->m_mutex);
return true;
}
if (waitTime_ms == 0xffffffff) {
while (!p->m_state && waitRet == 0) {
waitRet = pthread_cond_wait(&p->m_cond, &p->m_mutex);
}
}
else if (waitTime_ms != 0) {
struct timeval now;
struct timespec outtime;
gettimeofday(&now, NULL);
outtime.tv_sec = now.tv_sec + waitTime_ms / 1000;
outtime.tv_nsec = (now.tv_usec + (waitTime_ms % 1000) * 1000) * 1000;
if (outtime.tv_nsec >= 1000000000) {
++outtime.tv_sec;
outtime.tv_nsec -= 1000000000;
}
while (!p->m_state && waitRet == 0) {
waitRet = pthread_cond_timedwait(&p->m_cond, &p->m_mutex, &outtime);
}
if (waitRet == ETIMEDOUT) {
ret = false;
}
else
assert(waitRet == 0);
}
else
ret = p->m_state;
if (waitRet == 0 && !p->m_manualReset) {
p->m_state = false;
}
pthread_mutex_unlock(&p->m_mutex);
}
return ret;
}
void stResetEvent(EventHandle handle)
{
if (handle) {
st_Event_Info* p = (st_Event_Info*)handle;
if (p->m_state)
{
pthread_mutex_lock(&p->m_mutex);
p->m_state = false;
pthread_mutex_unlock(&p->m_mutex);
}
}
}
void stSetEvent(EventHandle handle)
{
if (handle) {
st_Event_Info* p = (st_Event_Info*)handle;
if (!p->m_state)
{
pthread_mutex_lock(&p->m_mutex);
p->m_state = true;
// 广播激活所有等待
pthread_cond_broadcast(&p->m_cond);
pthread_mutex_unlock(&p->m_mutex);
}
}
}
用法举例:
// 创建实例
EventHandle event = stCreateEvent(false, false);
...
// 线程1中等待信号
while(!stWaitEvent(event, 100)) {
// do something
}
...
// 线程2:设置有信号
stSetEvent(event);
...
// 用完释放
stReleaseEvent(event);