本文属于转载,原文链接如下:http://blog.csdn.net/chexlong/article/details/7080537

与其相关的一组API包括:pthread_mutex_init,pthread_cond_init,pthread_mutex_lock,pthread_cond_wait,pthread_mutex_unlock,pthread_cond_broadcast,pthread_cond_timedwait,pthread_cond_destroy,pthread_mutex_destroy。

MyEvent.h

#ifndef My_Event_Header
#define My_Event_Header #include <iostream>
#include <pthread.h>
#include <errno.h> using namespace std; //--------------------------------------------------------------- class CEventImpl
{
protected: /*
动态方式初始化互斥锁,初始化状态变量m_cond
`bAutoReset true 人工重置
false 自动重置
*/
CEventImpl(bool manualReset); /*
注销互斥锁,注销状态变量m_cond
*/
~CEventImpl(); /*
将当前事件对象设置为有信号状态
若自动重置,则等待该事件对象的所有线程只有一个可被调度
若人工重置,则等待该事件对象的所有线程变为可被调度
*/
void SetImpl(); /*
以当前事件对象,阻塞线程,将其永远挂起
直到事件对象被设置为有信号状态
*/
bool WaitImpl(); /*
以当前事件对象,阻塞线程,将其挂起指定时间间隔
之后线程自动恢复可调度
*/
bool WaitImpl(long milliseconds); /*
将当前事件对象设置为无信号状态
*/
void ResetImpl(); private:
bool m_manual;
volatile bool m_state;
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
}; inline void CEventImpl::SetImpl()
{
if (pthread_mutex_lock(&m_mutex))
cout<<"cannot signal event (lock)"<<endl; //设置状态变量为true,对应有信号
m_state = true; //cout<<"CEventImpl::SetImpl m_state = "<<m_state<<endl; //重新激活所有在等待m_cond变量的线程
if (pthread_cond_broadcast(&m_cond))
{
pthread_mutex_unlock(&m_mutex);
cout<<"cannot signal event"<<endl;
}
pthread_mutex_unlock(&m_mutex);
} inline void CEventImpl::ResetImpl()
{
if (pthread_mutex_lock(&m_mutex))
cout<<"cannot reset event"<<endl; //设置状态变量为false,对应无信号
m_state = false; //cout<<"CEventImpl::ResetImpl m_state = "<<m_state<<endl; pthread_mutex_unlock(&m_mutex);
} //--------------------------------------------------------------- class CMyEvent: private CEventImpl
{
public:
CMyEvent(bool bManualReset = true);
~CMyEvent(); void Set();
bool Wait();
bool Wait(long milliseconds);
bool TryWait(long milliseconds);
void Reset(); private:
CMyEvent(const CMyEvent&);
CMyEvent& operator = (const CMyEvent&);
}; inline void CMyEvent::Set()
{
SetImpl();
} inline bool CMyEvent::Wait()
{
return WaitImpl();
} inline bool CMyEvent::Wait(long milliseconds)
{
if (!WaitImpl(milliseconds))
{
cout<<"time out"<<endl;
return false;
}
else
{
return true;
}
} inline bool CMyEvent::TryWait(long milliseconds)
{
return WaitImpl(milliseconds);
} inline void CMyEvent::Reset()
{
ResetImpl();
} #endif

MyEvent.cpp

#include "MyEvent.h"
#include <sys/time.h> CEventImpl::CEventImpl(bool manualReset): m_manual(manualReset), m_state(false)
{
if (pthread_mutex_init(&m_mutex, NULL))
cout<<"cannot create event (mutex)"<<endl;
if (pthread_cond_init(&m_cond, NULL))
cout<<"cannot create event (condition)"<<endl;
} CEventImpl::~CEventImpl()
{
pthread_cond_destroy(&m_cond);
pthread_mutex_destroy(&m_mutex);
} bool CEventImpl::WaitImpl()
{
if (pthread_mutex_lock(&m_mutex))
{
cout<<"wait for event failed (lock)"<<endl;
return false;
}
while (!m_state)
{
//cout<<"CEventImpl::WaitImpl while m_state = "<<m_state<<endl; //对互斥体进行原子的解锁工作,然后等待状态信号
if (pthread_cond_wait(&m_cond, &m_mutex))
{
pthread_mutex_unlock(&m_mutex);
cout<<"wait for event failed"<<endl;
return false;
}
}
if (m_manual)
m_state = false;
pthread_mutex_unlock(&m_mutex); //cout<<"CEventImpl::WaitImpl end m_state = "<<m_state<<endl; return true;
} bool CEventImpl::WaitImpl(long milliseconds)
{
int rc = ;
struct timespec abstime;
struct timeval tv;
gettimeofday(&tv, NULL);
abstime.tv_sec = tv.tv_sec + milliseconds / ;
abstime.tv_nsec = tv.tv_usec* + (milliseconds % )*;
if (abstime.tv_nsec >= )
{
abstime.tv_nsec -= ;
abstime.tv_sec++;
} if (pthread_mutex_lock(&m_mutex) != )
{
cout<<"wait for event failed (lock)"<<endl;
return false;
}
while (!m_state)
{
//自动释放互斥体并且等待m_cond状态,并且限制了最大的等待时间
if ((rc = pthread_cond_timedwait(&m_cond, &m_mutex, &abstime)))
{
if (rc == ETIMEDOUT) break;
pthread_mutex_unlock(&m_mutex);
cout<<"cannot wait for event"<<endl;
return false;
}
}
if (rc == && m_manual)
m_state = false;
pthread_mutex_unlock(&m_mutex);
return rc == ;
} CMyEvent::CMyEvent(bool bManualReset): CEventImpl(bManualReset)
{
} CMyEvent::~CMyEvent()
{
}

测试代码如下所示:pthread_event.cpp

// pthread_event.cpp : 定义控制台应用程序的入口点。
// #include <unistd.h>
#include "MyEvent.h" #define PRINT_TIMES 10 //创建一个人工自动重置事件对象
CMyEvent g_myEvent;
int g_iNum = ; //线程函数1
void * ThreadProc1(void *pParam)
{
for (int i = ; i < PRINT_TIMES; i++)
{
g_iNum++;
cout<<"ThreadProc1 do print, Num = "<<g_iNum<<endl; //设置事件为有信号状态
g_myEvent.Set(); sleep();
} return (void *);
} //线程函数2
void * ThreadProc2(void *pParam)
{
bool bRet = false;
while ( )
{
if ( g_iNum >= PRINT_TIMES )
{
break;
} //以当前事件对象阻塞本线程,将其挂起
bRet = g_myEvent.Wait();
if ( bRet )
{
cout<<"ThreadProc2 do print, Num = "<<g_iNum<<endl; //设置事件为无信号状态
g_myEvent.Reset();
}
else
{
cout<<"ThreadProc2 system exception"<<endl;
}
} return (void *);
} int main(int argc, char* argv[])
{
pthread_t thread1,thread2;
pthread_attr_t attr1,attr2; //创建两个工作线程
pthread_attr_init(&attr1);
pthread_attr_setdetachstate(&attr1,PTHREAD_CREATE_JOINABLE);
if (pthread_create(&thread1,&attr1, ThreadProc1,NULL) == -)
{
cout<<"Thread 1: create failed"<<endl;
}
pthread_attr_init(&attr2);
pthread_attr_setdetachstate(&attr2,PTHREAD_CREATE_JOINABLE);
if (pthread_create(&thread2,&attr2, ThreadProc2,NULL) == -)
{
cout<<"Thread 2: create failed"<<endl;
} //等待线程结束
void *result;
pthread_join(thread1,&result);
pthread_join(thread2,&result); //关闭线程,释放资源
pthread_attr_destroy(&attr1);
pthread_attr_destroy(&attr2); int iWait;
cin>>iWait; return ;
}

编译运行结果如下所示:

Linux平台用C++实现事件对象,同步线程(转)的更多相关文章

  1. Linux平台用C++实现事件对象,同步线程

    前文在Win32平台上用C++实现了事件对象Event,对线程进行同步,以达到期望目的.这次在Linux平台上实现与之类似的事件对象.与其相关的一组API包括:pthread_mutex_init,p ...

  2. [C++] socket - 5 [API事件对象实现线程同步]

    /*API事件对象实现线程同步*/ #include<windows.h> #include<stdio.h> DWORD WINAPI myfun1(LPVOID lpPar ...

  3. 事件同步(一)-——CreateEvent( )事件对象实现线程同步

    事件对象分为两类:人工重置事件对象和自动重置事件对象.对于人工重置事件对象,可以同时有多个线程等待到事件对象,成为可调度线程. 对于自动重置事件对象,等待该事件对象的多个线程只能有一个线程成为可调度线 ...

  4. 转:VC++线程同步-事件对象

    这是整理孙鑫VC得到的关于线程同步方面的笔记. n       事件对象也属于内核对象,包含一个使用计数,一个用于指明该事件是一个自动重置的事件还是一个人工重置的事件的布尔值,另一个用于指明该事件处于 ...

  5. Windows多线程同步系列之三-----事件对象

    事件是一个内核事件,内核事件是什么呢,我理解也不深入也不好说,暂且理解为一个内核维护的数据类型吧通过内核事件同步主要 的方法是对事件的信号有和无来进行同步. 比如当我们一个线程进入一段临界代码(独占代 ...

  6. 第9章 用内核对象进行线程同步(1)_事件对象(Event)

    9.1 等待函数 (1)WaitForSingleObject(hObject,dwMilliseonds); ①dwMilliseconds为INFINITE时表示无限等待 ②dwMilliseco ...

  7. 转:sock_ev——linux平台socket事件框架(socket API的封装) .

    把linux平台提供的有关socket操作的API进行封装是有必要的:基于stream操作的流程与基于dgram操作的流程略有不同,分别放在两个类中,但两者又有很多相似的操作,因此写一个基类,让其继承 ...

  8. Linux 平台静默安装 Oracle客户端

    需求:Linux平台,安装完整版Oracle客户端 Tips:如果只是用到sqlldr,sqlplus功能,可以参考<Linux上oracle精简版客户端快速部署>快速部署精简版:如果需要 ...

  9. 【转】Redis安装整理(window平台和Linux平台)

    原文连接:http://zheng12tian.iteye.com/blog/1471726 原文作者:zheng12tian 转载注明以上信息! window平台Redis安装 redis wind ...

随机推荐

  1. BZOJ1202 [HNOI2005]狡猾的商人 【并查集】

    1202: [HNOI2005]狡猾的商人 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 4180  Solved: 2015 [Submit][S ...

  2. UVA.10986 Fractions Again (经典暴力)

    UVA.10986 Fractions Again (经典暴力) 题意分析 同样只枚举1个,根据条件算出另外一个. 代码总览 #include <iostream> #include &l ...

  3. Shell编程语法

    创建shell程序的步骤: 第一步:创建一个脚本文件.sh. 第二步:授予权限使它可以执行chmod u+x .sh 第三步:执行 ./example 或者 sh example 脚本调试:      ...

  4. bzoj2326:[HNOI2011]数学作业(分段矩阵乘法)

    题目大意:输入n(n<=10^18)和m,将1~n的整数连起来模m输出,比如n=13则输出12345678910111213模m的数. 设f[i]为1~i整数连起来模m的数,i的位数为k,则有f ...

  5. Apache 403 错误解决方法-让别人可以访问你的服务器(转)

    有一次做好了一个效果放在自己电脑的服务器上,让同学查看(同处于校园网中),却不知apache一直显示403 错误,对方没有权限访问,我知道这应该是配置文件httpd.conf中的问题,网上搜了一下其他 ...

  6. [mysql][【优化集合】mysql数据库优化集合

    三个层面: 1.系统层面 2.mysql配置参数 3.sql语句优化 =========================================================== 一.系统层 ...

  7. 求前n项正整数的倒数和

    求前n项正整数的倒数和 前n项正整数的和是一个发散的序列,学过高等数学的这个都知道.所以它没有一个精确的公式,但是近似的公式是有的: 1 + 1/2 + 1/3 + …… + 1/n ≍ ln n + ...

  8. POJ 3111 二分

    K Best Time Limit: 8000MS   Memory Limit: 65536K Total Submissions: 10507   Accepted: 2709 Case Time ...

  9. 在MVC5中使用Ninject 依赖注入

    各大主流.Net的IOC框架性能测试比较 : http://www.cnblogs.com/liping13599168/archive/2011/07/17/2108734.html 使用NuGet ...

  10. HDU 4609 FFT模板

    http://acm.hdu.edu.cn/showproblem.php?pid=4609 题意:给你n个数,问任意取三边能够,构成三角形的概率为多少. 思路:使用FFT对所有长度的个数进行卷积(\ ...