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

摘要:
前文在Win32平台上用C++实现了事件对象Event,对线程进行同步,以达到期望目的。这次在Linux平台上实现与之类似的事件对象。与其相关的一组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。下边,是封装的事件对象类,以及测试代码。

前文在Win32平台上用C++实现了事件对象Event,对线程进行同步,以达到期望目的。这次在Linux平台上实现与之类似的事件对象。与其相关的一组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。这些API的说明可以在这里找到:http://www.9linux.com/。下边,是封装的事件对象类,以及测试代码。使用VS2005编辑,在虚拟机 Fedora 13中编译,测试通过。

MyEvent.h

  1. #ifndefMy_Event_Header
  2. #defineMy_Event_Header
  3. #include<iostream>
  4. #include<pthread.h>
  5. #include<errno.h>
  6. usingnamespacestd;
  7. //---------------------------------------------------------------
  8. classCEventImpl
  9. {
  10. protected:
  11. /*
  12. 动态方式初始化互斥锁,初始化状态变量m_cond
  13. `bAutoResettrue人工重置
  14. false自动重置
  15. */
  16. CEventImpl(boolmanualReset);
  17. /*
  18. 注销互斥锁,注销状态变量m_cond
  19. */
  20. ~CEventImpl();
  21. /*
  22. 将当前事件对象设置为有信号状态
  23. 若自动重置,则等待该事件对象的所有线程只有一个可被调度
  24. 若人工重置,则等待该事件对象的所有线程变为可被调度
  25. */
  26. voidSetImpl();
  27. /*
  28. 以当前事件对象,阻塞线程,将其永远挂起
  29. 直到事件对象被设置为有信号状态
  30. */
  31. boolWaitImpl();
  32. /*
  33. 以当前事件对象,阻塞线程,将其挂起指定时间间隔
  34. 之后线程自动恢复可调度
  35. */
  36. boolWaitImpl(longmilliseconds);
  37. /*
  38. 将当前事件对象设置为无信号状态
  39. */
  40. voidResetImpl();
  41. private:
  42. boolm_manual;
  43. volatileboolm_state;
  44. pthread_mutex_tm_mutex;
  45. pthread_cond_tm_cond;
  46. };
  47. inlinevoidCEventImpl::SetImpl()
  48. {
  49. if(pthread_mutex_lock(&m_mutex))
  50. cout<<"cannotsignalevent(lock)"<<endl;
  51. //设置状态变量为true,对应有信号
  52. m_state=true;
  53. //cout<<"CEventImpl::SetImplm_state="<<m_state<<endl;
  54. //重新激活所有在等待m_cond变量的线程
  55. if(pthread_cond_broadcast(&m_cond))
  56. {
  57. pthread_mutex_unlock(&m_mutex);
  58. cout<<"cannotsignalevent"<<endl;
  59. }
  60. pthread_mutex_unlock(&m_mutex);
  61. }
  62. inlinevoidCEventImpl::ResetImpl()
  63. {
  64. if(pthread_mutex_lock(&m_mutex))
  65. cout<<"cannotresetevent"<<endl;
  66. //设置状态变量为false,对应无信号
  67. m_state=false;
  68. //cout<<"CEventImpl::ResetImplm_state="<<m_state<<endl;
  69. pthread_mutex_unlock(&m_mutex);
  70. }
  71. //---------------------------------------------------------------
  72. classCMyEvent:privateCEventImpl
  73. {
  74. public:
  75. CMyEvent(boolbManualReset=true);
  76. ~CMyEvent();
  77. voidSet();
  78. boolWait();
  79. boolWait(longmilliseconds);
  80. boolTryWait(longmilliseconds);
  81. voidReset();
  82. private:
  83. CMyEvent(constCMyEvent&);
  84. CMyEvent&operator=(constCMyEvent&);
  85. };
  86. inlinevoidCMyEvent::Set()
  87. {
  88. SetImpl();
  89. }
  90. inlineboolCMyEvent::Wait()
  91. {
  92. returnWaitImpl();
  93. }
  94. inlineboolCMyEvent::Wait(longmilliseconds)
  95. {
  96. if(!WaitImpl(milliseconds))
  97. {
  98. cout<<"timeout"<<endl;
  99. returnfalse;
  100. }
  101. else
  102. {
  103. returntrue;
  104. }
  105. }
  106. inlineboolCMyEvent::TryWait(longmilliseconds)
  107. {
  108. returnWaitImpl(milliseconds);
  109. }
  110. inlinevoidCMyEvent::Reset()
  111. {
  112. ResetImpl();
  113. }
  114. #endif

MyEvent.cpp

  1. #include"MyEvent.h"
  2. #include<sys/time.h>
  3. CEventImpl::CEventImpl(boolmanualReset):m_manual(manualReset),m_state(false)
  4. {
  5. if(pthread_mutex_init(&m_mutex,NULL))
  6. cout<<"cannotcreateevent(mutex)"<<endl;
  7. if(pthread_cond_init(&m_cond,NULL))
  8. cout<<"cannotcreateevent(condition)"<<endl;
  9. }
  10. CEventImpl::~CEventImpl()
  11. {
  12. pthread_cond_destroy(&m_cond);
  13. pthread_mutex_destroy(&m_mutex);
  14. }
  15. boolCEventImpl::WaitImpl()
  16. {
  17. if(pthread_mutex_lock(&m_mutex))
  18. {
  19. cout<<"waitforeventfailed(lock)"<<endl;
  20. returnfalse;
  21. }
  22. while(!m_state)
  23. {
  24. //cout<<"CEventImpl::WaitImplwhilem_state="<<m_state<<endl;
  25. //对互斥体进行原子的解锁工作,然后等待状态信号
  26. if(pthread_cond_wait(&m_cond,&m_mutex))
  27. {
  28. pthread_mutex_unlock(&m_mutex);
  29. cout<<"waitforeventfailed"<<endl;
  30. returnfalse;
  31. }
  32. }
  33. if(m_manual)
  34. m_state=false;
  35. pthread_mutex_unlock(&m_mutex);
  36. //cout<<"CEventImpl::WaitImplendm_state="<<m_state<<endl;
  37. returntrue;
  38. }
  39. boolCEventImpl::WaitImpl(longmilliseconds)
  40. {
  41. intrc=0;
  42. structtimespecabstime;
  43. structtimevaltv;
  44. gettimeofday(&tv,NULL);
  45. abstime.tv_sec=tv.tv_sec+milliseconds/1000;
  46. abstime.tv_nsec=tv.tv_usec*1000+(milliseconds%1000)*1000000;
  47. if(abstime.tv_nsec>=1000000000)
  48. {
  49. abstime.tv_nsec-=1000000000;
  50. abstime.tv_sec++;
  51. }
  52. if(pthread_mutex_lock(&m_mutex)!=0)
  53. {
  54. cout<<"waitforeventfailed(lock)"<<endl;
  55. returnfalse;
  56. }
  57. while(!m_state)
  58. {
  59. //自动释放互斥体并且等待m_cond状态,并且限制了最大的等待时间
  60. if((rc=pthread_cond_timedwait(&m_cond,&m_mutex,&abstime)))
  61. {
  62. if(rc==ETIMEDOUT)break;
  63. pthread_mutex_unlock(&m_mutex);
  64. cout<<"cannotwaitforevent"<<endl;
  65. returnfalse;
  66. }
  67. }
  68. if(rc==0&&m_manual)
  69. m_state=false;
  70. pthread_mutex_unlock(&m_mutex);
  71. returnrc==0;
  72. }
  73. CMyEvent::CMyEvent(boolbManualReset):CEventImpl(bManualReset)
  74. {
  75. }
  76. CMyEvent::~CMyEvent()
  77. {
  78. }

下边是测试代码

  1. //pthread_event.cpp:定义控制台应用程序的入口点。
  2. //
  3. #include<unistd.h>
  4. #include"MyEvent.h"
  5. #definePRINT_TIMES10
  6. //创建一个人工自动重置事件对象
  7. CMyEventg_myEvent;
  8. intg_iNum=0;
  9. //线程函数1
  10. void*ThreadProc1(void*pParam)
  11. {
  12. for(inti=0;i<PRINT_TIMES;i++)
  13. {
  14. g_iNum++;
  15. cout<<"ThreadProc1doprint,Num="<<g_iNum<<endl;
  16. //设置事件为有信号状态
  17. g_myEvent.Set();
  18. sleep(1);
  19. }
  20. return(void*)0;
  21. }
  22. //线程函数2
  23. void*ThreadProc2(void*pParam)
  24. {
  25. boolbRet=false;
  26. while(1)
  27. {
  28. if(g_iNum>=PRINT_TIMES)
  29. {
  30. break;
  31. }
  32. //以当前事件对象阻塞本线程,将其挂起
  33. bRet=g_myEvent.Wait();
  34. if(bRet)
  35. {
  36. cout<<"ThreadProc2doprint,Num="<<g_iNum<<endl;
  37. //设置事件为无信号状态
  38. g_myEvent.Reset();
  39. }
  40. else
  41. {
  42. cout<<"ThreadProc2systemexception"<<endl;
  43. }
  44. }
  45. return(void*)0;
  46. }
  47. intmain(intargc,char*argv[])
  48. {
  49. pthread_tthread1,thread2;
  50. pthread_attr_tattr1,attr2;
  51. //创建两个工作线程
  52. pthread_attr_init(&attr1);
  53. pthread_attr_setdetachstate(&attr1,PTHREAD_CREATE_JOINABLE);
  54. if(pthread_create(&thread1,&attr1,ThreadProc1,NULL)==-1)
  55. {
  56. cout<<"Thread1:createfailed"<<endl;
  57. }
  58. pthread_attr_init(&attr2);
  59. pthread_attr_setdetachstate(&attr2,PTHREAD_CREATE_JOINABLE);
  60. if(pthread_create(&thread2,&attr2,ThreadProc2,NULL)==-1)
  61. {
  62. cout<<"Thread2:createfailed"<<endl;
  63. }
  64. //等待线程结束
  65. void*result;
  66. pthread_join(thread1,&result);
  67. pthread_join(thread2,&result);
  68. //关闭线程,释放资源
  69. pthread_attr_destroy(&attr1);
  70. pthread_attr_destroy(&attr2);
  71. intiWait;
  72. cin>>iWait;
  73. return0;
  74. }

编译,运行。可以看到,与Win32平台上的测试结果相同,好神奇!

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

from:http://blog.csdn.net/chexlong/article/details/7080537

免责声明:文章转载自《Linux平台用C++实现事件对象,同步线程》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇二、实践与视频解决方案p标签多行文字内容实现上下垂直居中兼容ie8下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

linux清理内存命令

  1.清理前内存使用情况 free -m 2.开始清理  echo 1 > /proc/sys/vm/drop_caches3.清理后内存使用情况 free -m4.完成!查看内存条数命令: dmidecode | grep -A16 "Memory Device$" ++++++++++++++++++++++++++++++++++++...

关于deepin如何把CD制作成iso的测试

这不是无聊的测试。之前论坛里有朋友寻问deepin如何把cd制作成iso,有提问就应该有需求,一般大神的回答只是提示几个关键词,所以我们小白是理解不透的。 为了搞清楚这个问题,老陌本着实事求事的态度测试了一下,最终老陌测试成功,收获了知识与喜悦。下面把我的测试步骤整理分享一下: 由于没有光驱,老陌早上起来在虚拟机里安装了深度操作系统,这样在虚拟机中就有光驱...

WPF 不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改

该问题出现在WPF中的VM类中,ObservableCollection类型,该类型的 CollectionView 不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改,解决办法: ThreadPool.QueueUserWorkItem(delegate { Synch...

Android Handler与多线程

本文首先解释一下handler是用来干嘛的,然后通过例子介绍其在多线程中的应用。 什么是Handler      handler通俗一点讲就是用来在各个进程之间发送数据的处理对象。在任何进程中,只要获得了另一个进程的handler则可以通过 handler.sendMessage(message)方法向那个进程发送数据。基于这个机制,我们在处理多线程的时...

Linux-c给线程取名字

https://blog.csdn.net/jasonchen_gbd/article/details/51308638 1 #define wtm_set_thread_name(n) ({ 2 char tname[THREAD_NAME_LEN + 1] = ""; 3 if (strlen(n) > THREAD_N...

查看linux操作系统版本

转自:https://www.cnblogs.com/vaelailai/p/7545166.html 一、linux下如何查看已安装的centos版本信息: 1.Linux查看当前操作系统版本信息  cat /proc/version Linux version 2.6.32-696.el6.x86_64 (mockbuild@c1bm.rdu2.cen...