首页 > 系统相关 >跨平台实现Event事件(Linux+win)

跨平台实现Event事件(Linux+win)

时间:2023-03-15 18:12:45浏览次数:39  
标签:return hevent win pthread 跨平台 mutex Linux bool event

1、第一种方法(win和linux通用)

//头文件.h
#ifndef _HIK_EVENT_H_   
#define _HIK_EVENT_H_  
  
#ifdef _MSC_VER  
#include <Windows.h>  
#define hik_event_handle HANDLE  
#else  
#include <pthread.h>  
typedef struct    
{  
    bool state;  
    bool manual_reset;  
    pthread_mutex_t mutex;  
    pthread_cond_t cond;  
}event_t;  
#define event_handle event_t*  
#endif  
  
//返回值:NULL 出错  
event_handle event_create(bool manual_reset, bool init_state);  
  
//返回值:0 等到事件,-1出错  
int event_wait(event_handle hevent);  
  
//返回值:0 等到事件,1 超时,-1出错  
int event_timedwait(event_handle hevent, long milliseconds);  
  
//返回值:0 成功,-1出错  
int event_set(event_handle hevent);  
  
//返回值:0 成功,-1出错  
int event_reset(event_handle hevent);  
  
//返回值:无  
void event_destroy(event_handle hevent);  
  
#endif  
  
/// 
//源文件.cpp:
#include "event.h"  
#ifdef __linux  
#include <sys/time.h>  
#include <errno.h>  
#endif  
#include <iostream>  
event_handle event_create(bool manual_reset, bool init_state)  
{     
#ifdef _MSC_VER  
    HANDLE hevent = CreateEvent(NULL, manual_reset, init_state, NULL);  
#else  
    event_handle hevent = new(std::nothrow) event_t;  
    if (hevent == NULL)  
    {  
        return NULL;  
    }  
    hevent->state = init_state;  
    hevent->manual_reset = manual_reset;  
    if (pthread_mutex_init(&hevent->mutex, NULL))  
    {  
        delete hevent;  
        return NULL;  
    }  
    if (pthread_cond_init(&hevent->cond, NULL))  
    {  
        pthread_mutex_destroy(&hevent->mutex);  
        delete hevent;  
        return NULL;  
    }  
#endif  
    return hevent;  
}  
int event_wait(event_handle hevent)  
{  
#ifdef _MSC_VER  
    DWORD ret = WaitForSingleObject(hevent, INFINITE);  
    if (ret == WAIT_OBJECT_0)  
    {  
        return 0;  
    }  
    return -1;  
#else  
    if (pthread_mutex_lock(&hevent->mutex))     
    {        
        return -1;     
    }     
    while (!hevent->state)      
    {        
        if (pthread_cond_wait(&hevent->cond, &hevent->mutex))     
        {     
            pthread_mutex_unlock(&hevent->mutex);   
            return -1;     
        }     
    }     
    if (!hevent->manual_reset)   
    {  
        hevent->state = false;  
    }  
    if (pthread_mutex_unlock(&hevent->mutex))     
    {       
        return -1;     
    }    
    return 0;  
#endif  
}  
int event_timedwait(event_handle hevent, long milliseconds)  
{  
#ifdef _MSC_VER  
    DWORD ret = WaitForSingleObject(hevent, milliseconds);  
    if (ret == WAIT_OBJECT_0)  
    {  
        return 0;  
    }  
    if (ret == WAIT_TIMEOUT)  
    {  
        return 1;  
    }  
    return -1;  
#else  
  
    int rc = 0;     
    struct timespec abstime;     
    struct timeval tv;     
    gettimeofday(&tv, NULL);     
    abstime.tv_sec  = tv.tv_sec + milliseconds / 1000;     
    abstime.tv_nsec = tv.tv_usec*1000 + (milliseconds % 1000)*1000000;     
    if (abstime.tv_nsec >= 1000000000)     
    {     
        abstime.tv_nsec -= 1000000000;     
        abstime.tv_sec++;     
    }     
  
    if (pthread_mutex_lock(&hevent->mutex) != 0)     
    {       
        return -1;     
    }     
    while (!hevent->state)      
    {        
        if (rc = pthread_cond_timedwait(&hevent->cond, &hevent->mutex, &abstime))     
        {     
            if (rc == ETIMEDOUT) break;     
            pthread_mutex_unlock(&hevent->mutex);      
            return -1;     
        }     
    }     
    if (rc == 0 && !hevent->manual_reset)     
    {  
        hevent->state = false;  
    }  
    if (pthread_mutex_unlock(&hevent->mutex) != 0)     
    {        
        return -1;     
    }  
    if (rc == ETIMEDOUT)  
    {  
        //timeout return 1  
        return 1;  
    }  
    //wait event success return 0  
    return 0;  
#endif  
}  
int event_set(event_handle hevent)  
{  
#ifdef _MSC_VER  
    return !SetEvent(hevent);  
#else  
    if (pthread_mutex_lock(&hevent->mutex) != 0)  
    {  
        return -1;  
    }  
  
    hevent->state = true;  
  
    if (hevent->manual_reset)  
    {  
        if(pthread_cond_broadcast(&hevent->cond))  
        {  
            return -1;  
        }  
    }  
    else  
    {  
        if(pthread_cond_signal(&hevent->cond))  
        {  
            return -1;  
        }  
    }  
  
    if (pthread_mutex_unlock(&hevent->mutex) != 0)  
    {  
        return -1;  
    }  
  
    return 0;  
#endif  
}  
int event_reset(event_handle hevent)   
{  
#ifdef _MSC_VER  
    //ResetEvent 返回非零表示成功  
    if (ResetEvent(hevent))  
    {  
        return 0;  
    }   
    return -1;  
#else  
    if (pthread_mutex_lock(&hevent->mutex) != 0)  
    {  
        return -1;  
    }  
  
    hevent->state = false;  
  
    if (pthread_mutex_unlock(&hevent->mutex) != 0)  
    {        
        return -1;  
    }  
    return 0;  
#endif  
}  
void event_destroy(event_handle hevent)  
{  
#ifdef _MSC_VER  
    CloseHandle(hevent);  
#else  
    pthread_cond_destroy(&hevent->cond);  
    pthread_mutex_destroy(&hevent->mutex);  
    delete hevent;  
#endif  
}
2、第二种方法(linux下实现win的event)

(1)头文件

首先是event.h文件,实现event类

#include <pthread.h>
#include <sys/time.h>
 
const int INFINITE = -1;
class CEvent
{
public:
    CEvent(bool bIsManualReset, bool bInitialSignaled);
    ~CEvent();
    bool CreateEvent();
    bool Set();
    bool Reset();
    bool Wait(int cms);
private:
    bool EnsureInitialized();
    bool m_bIsManualReset;
    bool m_bEventStatus;
    bool m_bMutexInitialized;
    pthread_mutex_t m_mutex;
    bool m_bCondInitialized;
    pthread_cond_t m_cond;
};
 
CEvent::CEvent(bool bIsManualReset, bool bInitialSignaled)
: m_bIsManualReset(bIsManualReset)
, m_bEventStatus(bInitialSignaled)
, m_bMutexInitialized(false)
, m_bCondInitialized(false)
{
    
}
 
CEvent::~CEvent()
{
    if (m_bMutexInitialized)
    {
        pthread_mutex_destroy(&m_mutex);
        m_bMutexInitialized = false; 
    }
 
    if (m_bCondInitialized)
    {
        pthread_cond_destroy(&m_cond);
        m_bCondInitialized = false;   
    }
}
 
 
bool CEvent::CreateEvent()
{
    if (!m_bMutexInitialized)
    {
        if (0 == pthread_mutex_init(&m_mutex, NULL))
        {
            m_bMutexInitialized = true; 
        }
    }
 
    if (!m_bCondInitialized)
    {
        if (0 == pthread_cond_init(&m_cond, NULL))
        {
            m_bCondInitialized = true;   
        }
    }
 
    return ( m_bMutexInitialized && m_bCondInitialized); 
}
 
bool CEvent::EnsureInitialized()
{
    return ( m_bMutexInitialized && m_bCondInitialized); 
}
 
bool CEvent::Set()
{
    if (!EnsureInitialized())
    {
        return false;
    }    
 
    pthread_mutex_lock(&m_mutex);
    m_bEventStatus = true;
    pthread_cond_broadcast(&m_cond);
    pthread_mutex_unlock(&m_mutex);
    return true;    
}
 
bool CEvent::Reset()
{
    if (!EnsureInitialized())
    {
        return false;
    }
 
    pthread_mutex_lock(&m_mutex);
    m_bEventStatus = false;
    pthread_mutex_unlock(&m_mutex);
    return true;    
}
 
bool CEvent::Wait(int cms)
{
    if (!EnsureInitialized())
    {
        return false;
    }
 
    pthread_mutex_lock(&m_mutex);
    int error = 0;
 
    if (cms != INFINITE)
    {
        struct timeval tv;
        gettimeofday(&tv, NULL);
 
        struct timespec ts;
        ts.tv_sec = tv.tv_sec + (cms / 1000);
        ts.tv_nsec = tv.tv_usec * 1000 + (cms % 1000) * 1000000; 
 
        if (ts.tv_nsec >= 1000000000)
        {
            ts.tv_sec++;
            ts.tv_nsec -= 1000000000;
        }
 
        while ((!m_bEventStatus) && (error == 0))
        {
            error = pthread_cond_timedwait(&m_cond, &m_mutex, &ts);
        }
    }
    else
    {
        while ((!m_bEventStatus) && (error == 0))
        {
            error = pthread_cond_wait(&m_cond, &m_mutex);
        }
    }
 
    if (0 == error && !m_bIsManualReset)
    {
        m_bEventStatus = false;
    } 
 
    pthread_mutex_unlock(&m_mutex);
 
    return (0 == error);
}
 
(2)接下来是调用event类的文件main.cpp:

#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#include "event.h"
CEvent *g_event = NULL;
 
CEvent *CreateEvent(bool bManualReset, bool bInitialState)
{
    CEvent *pEvent = new CEvent(bManualReset, bInitialState);
    assert(pEvent);
 
    bool bRet = pEvent->CreateEvent();
    assert(bRet);
 
    return pEvent;
}
 
unsigned int WaitForSingleObject(CEvent *pEvent, int cms)
{
    assert(pEvent);
    if( pEvent->Wait(cms) )
    {
        return 0;
    }
 
    return 1;
}
 
bool CloseHandle(CEvent *pEvent)
{
    delete pEvent;
}
 
bool SetEvent(CEvent *pEvent)
{
    pEvent->Set();
}
 
bool ResetEvent(CEvent *pEvent)
{
    pEvent->Reset();
}
 
void *pFunc1(void *pEvent)
{
    while (1)
    {
        WaitForSingleObject(g_event, INFINITE);
        printf("this is func1 print!\n");
        sleep(1);
        ResetEvent(g_event); 
    }
}
 
void *pFunc2(void *pEvent)
{
    while (1)
    {
        sleep(5);
        printf("this is func2 print!\n");
        SetEvent(g_event);
    }
}
 
int main()
{
    
    //g_event = CreateEvent(false, true);
    g_event = CreateEvent(true, true);
 
    pthread_t pid1;
    pthread_t pid2;
 
    pthread_create(&pid1, NULL, pFunc1, NULL); 
    pthread_create(&pid2, NULL, pFunc2, NULL); 
    
    pthread_join(pid1, NULL); 
    pthread_join(pid2, NULL);
    
    CloseHandle(g_event);
    return 0;  
}
在main.cpp文件中对事件类进行的使用函数进行封装,然后在两个线程中可以采用类似于windows中使用事件的形式来使用。上面的event事件同windows下一样,支持手动和自动。

标签:return,hevent,win,pthread,跨平台,mutex,Linux,bool,event
From: https://www.cnblogs.com/lidabo/p/17219476.html

相关文章

  • 修改linux shell 提示符
    远程登录虚拟机,linuxshell提示符为-bash-4.1$要把这个提示符改掉 1、新建~/.bash_profile文件-bash-4.1$vi~/.bash_profile-bash-4.1$cat ~/.bash_profilecat:......
  • 浅谈Linux下的shell--BASH
    shell的概念与作用我们已经学习并知道了操作系统实际上就是一款软件,一款用来管理计算机软硬件资源,为用户提供良好的执行环境的软件。假如该软件能被用户随意操作,就会有可能......
  • linux系统如何查看是否是线程死锁,多线程中如何使用gdb精确定位死锁问题
    在多线程开发过程中很多人应该都会遇到死锁问题,死锁问题也是面试过程中经常被问到的问题,这里介绍在c++中如何使用gdb+python脚本调试死锁问题,以及如何在程序运行过程中......
  • windows常用快捷键
    windows常用快捷键复制ctrl+c粘贴ctrl+v全选ctrl+a剪切ctrl+r撤销ctrl+z保存ctrl+s关闭窗口ctrl+F4永久删除shift+delete运行win+r我的电脑win+e任务......
  • libunwind安装问题
    一、unknowntypename'pthread_mutex_t'在dwarf.h添加头文件二、multipledefinitionof`_U_dyn_info_list'gcc版本太新,可以降版本,也可以在configure添加-fcommon编......
  • Linux开启root用户远程登录
    Linux开启root用户远程登录开启root账户,给root用户设置密码sudopasswdroot输入两遍密码修改配置文件打开SSH配置文件。vim/etc/ssh/sshd_config修改如下参......
  • mysql安装详细文档(windows)
    安装MySQLMySQL是目前最为流行的开放源码的数据库,是完全网络化的跨平台的关系型数据库系统,它是由瑞典MySQLAB公司开发,目前属于Oracle公司。任何人都能从Internet下载MySQL......
  • linux自定义man搜索路径
    很多时候,在linux我们源码编译库代码时候会自定义安装路径,这使得man查询的时候无法找到库文档,默认的man搜索路径可以使用下面命令查看:$man-w/usr/local/share/man:/usr/......
  • Linux基础
    常用命令cd  :  切换文件夹  cd/home 绝对路径,以根目录开头  cd admin 相对路径,  cd..返回上一层目录  cd~回到自己家目录  cd-回看......
  • Linux下文档的压缩与打包
    Linux下最常见的压缩文件通常都是.tar.gz格式的,除此之外还有.tar、.gz、.bz2、.zip下面介绍Linux下最常见的后缀名所对应的压缩工具:.gz:表示由gzip压缩工具压缩的文件。......