关键词搜索

源码搜索 ×
×

tars源码分析之22

发布2022-07-17浏览611次

详情内容

信号量互斥,怎么写?

  1. #include <errno.h>
  2. #include <string.h>
  3. #include "util/tc_sem_mutex.h"
  4. namespace tars
  5. {
  6. TC_SemMutex::TC_SemMutex():_semID(-1),_semKey(-1)
  7. {
  8. }
  9. TC_SemMutex::TC_SemMutex(key_t iKey)
  10. {
  11. init(iKey);
  12. }
  13. void TC_SemMutex::init(key_t iKey)
  14. {
  15. #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
  16. /* union semun is defined by including <sys/sem.h> */
  17. #else
  18. /* according to X/OPEN we have to define it ourselves */
  19. union semun
  20. {
  21. int val; /* value for SETVAL */
  22. struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
  23. unsigned short *array; /* array for GETALL, SETALL */
  24. /* Linux specific part: */
  25. struct seminfo *__buf; /* buffer for IPC_INFO */
  26. };
  27. #endif
  28. int iSemID;
  29. union semun arg;
  30. u_short array[2] = { 0, 0 };
  31. //生成信号量集, 包含两个信号量
  32. if ( (iSemID = semget( iKey, 2, IPC_CREAT | IPC_EXCL | 0666)) != -1 )
  33. {
  34. arg.array = &array[0];
  35. //将所有信号量的值设置为0
  36. if ( semctl( iSemID, 0, SETALL, arg ) == -1 )
  37. {
  38. throw TC_SemMutex_Exception("[TC_SemMutex::init] semctl error:" + string(strerror(errno)));
  39. }
  40. }
  41. else
  42. {
  43. //信号量已经存在
  44. if ( errno != EEXIST )
  45. {
  46. throw TC_SemMutex_Exception("[TC_SemMutex::init] sem has exist error:" + string(strerror(errno)));
  47. }
  48. //连接信号量
  49. if ( (iSemID = semget( iKey, 2, 0666 )) == -1 )
  50. {
  51. throw TC_SemMutex_Exception("[TC_SemMutex::init] connect sem error:" + string(strerror(errno)));
  52. }
  53. }
  54. _semKey = iKey;
  55. _semID = iSemID;
  56. }
  57. int TC_SemMutex::rlock() const
  58. {
  59. //进入共享锁, 第二个信号量的值表示当前使用信号量的进程个数
  60. //等待第一个信号量变为0(排他锁没有使用)
  61. //占用第二个信号量(第二个信号量值+1, 表示被共享锁使用)
  62. struct sembuf sops[2] = { {0, 0, SEM_UNDO}, {1, 1, SEM_UNDO} };
  63. size_t nsops = 2;
  64. int ret = -1;
  65. do
  66. {
  67. ret=semop(_semID,&sops[0],nsops);
  68. } while ((ret == -1) &&(errno==EINTR));
  69. return ret;
  70. //return semop( _semID, &sops[0], nsops);
  71. }
  72. int TC_SemMutex::unrlock( ) const
  73. {
  74. //解除共享锁, 有进程使用过第二个信号量
  75. //等到第二个信号量可以使用(第二个信号量的值>=1)
  76. struct sembuf sops[1] = { {1, -1, SEM_UNDO} };
  77. size_t nsops = 1;
  78. int ret = -1;
  79. do
  80. {
  81. ret=semop(_semID,&sops[0],nsops);
  82. } while ((ret == -1) &&(errno==EINTR));
  83. return ret;
  84. //return semop( _semID, &sops[0], nsops);
  85. }
  86. bool TC_SemMutex::tryrlock() const
  87. {
  88. struct sembuf sops[2] = { {0, 0, SEM_UNDO|IPC_NOWAIT}, {1, 1, SEM_UNDO|IPC_NOWAIT}};
  89. size_t nsops = 2;
  90. int iRet = semop( _semID, &sops[0], nsops );
  91. if(iRet == -1)
  92. {
  93. if(errno == EAGAIN)
  94. {
  95. //无法获得锁
  96. return false;
  97. }
  98. else
  99. {
  100. throw TC_SemMutex_Exception("[TC_SemMutex::tryrlock] semop error : " + string(strerror(errno)));
  101. }
  102. }
  103. return true;
  104. }
  105. int TC_SemMutex::wlock() const
  106. {
  107. //进入排他锁, 第一个信号量和第二个信号都没有被使用过(即, 两个锁都没有被使用)
  108. //等待第一个信号量变为0
  109. //等待第二个信号量变为0
  110. //释放第一个信号量(第一个信号量+1, 表示有一个进程使用第一个信号量)
  111. struct sembuf sops[3] = { {0, 0, SEM_UNDO}, {1, 0, SEM_UNDO}, {0, 1, SEM_UNDO} };
  112. size_t nsops = 3;
  113. int ret = -1;
  114. do
  115. {
  116. ret=semop(_semID,&sops[0],nsops);
  117. } while ((ret == -1) &&(errno==EINTR));
  118. return ret;
  119. //return semop( _semID, &sops[0], nsops);
  120. }
  121. int TC_SemMutex::unwlock() const
  122. {
  123. //解除排他锁, 有进程使用过第一个信号量
  124. //等待第一个信号量(信号量值>=1)
  125. struct sembuf sops[1] = { {0, -1, SEM_UNDO} };
  126. size_t nsops = 1;
  127. int ret = -1;
  128. do
  129. {
  130. ret=semop(_semID,&sops[0],nsops);
  131. } while ((ret == -1) &&(errno==EINTR));
  132. return ret;
  133. //return semop( _semID, &sops[0], nsops);
  134. }
  135. bool TC_SemMutex::trywlock() const
  136. {
  137. struct sembuf sops[3] = { {0, 0, SEM_UNDO|IPC_NOWAIT}, {1, 0, SEM_UNDO|IPC_NOWAIT}, {0, 1, SEM_UNDO|IPC_NOWAIT} };
  138. size_t nsops = 3;
  139. int iRet = semop( _semID, &sops[0], nsops );
  140. if(iRet == -1)
  141. {
  142. if(errno == EAGAIN)
  143. {
  144. //无法获得锁
  145. return false;
  146. }
  147. else
  148. {
  149. throw TC_SemMutex_Exception("[TC_SemMutex::trywlock] semop error : " + string(strerror(errno)));
  150. }
  151. }
  152. return true;
  153. }
  154. }

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载