SignalTemplate.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. //
  2. // "$Id: SignalTemplate.h 108093 2013-03-26 02:55:14Z wang_haifeng $"
  3. //
  4. // Copyright (c)1992-2007, ZheJiang Dahua Technology Stock CO.LTD.
  5. // All Rights Reserved.
  6. //
  7. // Description:
  8. // Revisions: Year-Month-Day SVN-Author Modification
  9. //
  10. /// \class SIGNAL_SIGNAL
  11. /// \brief 信号类模块。
  12. ///
  13. /// 一个信号被触发时,会调用所有连接到其上的TFunctionN对象,只支持
  14. /// 返回值为void的TFunctionN。SIGNAL_SIGNAL是一个宏,根据参数个数会被替换成
  15. /// TSignalN,用户通过 TSignalN<T1, T2, T3,..,TN>方式来使用,TN表示参数类型,
  16. /// N表示函数参数个数,目前最大参数为6。
  17. /// \see FUNCTION_FUNCTION
  18. #define SIGNAL_SIGNAL DAHUA_JOIN(TSignal,SIGNAL_NUMBER)
  19. #define FUNCTION_FUNCTION DAHUA_JOIN(TFunction, SIGNAL_NUMBER)
  20. #if (SIGNAL_NUMBER != 0)
  21. template <SIGNAL_CLASS_TYPES>
  22. #endif
  23. class SIGNAL_SIGNAL
  24. {
  25. /// 信号节点状态
  26. enum SlotState
  27. {
  28. slotStateEmpty, ///< 节点为空
  29. slotStateNormal, ///< 节点以连接
  30. };
  31. public:
  32. /// 节点挂载的位置
  33. enum SlotPosition
  34. {
  35. any, ///< 任意地方
  36. back, ///< 挂载在末尾
  37. front ///< 挂载在头部
  38. };
  39. /// 信号操作错误码
  40. enum ErrorCode
  41. {
  42. errorNoFound = -1, ///< 没有找到制定的对象
  43. errorExist = -2, ///< 对象已经存在
  44. errorFull = -3, ///< 已经到达能够连接的对象个数上限
  45. errorEmptyProc = -4, ///< 对象包含的函数指针为空,没有意义
  46. errorAllReuseProc = -5,///< 任意远程函数指针,没有意义
  47. };
  48. /// 与信号模板参数类型匹配的函数指针对象类型
  49. typedef FUNCTION_FUNCTION<void SIGNAL_TYPES_COMMA> Proc;
  50. private:
  51. /// 信号节点结构
  52. struct SignalSlot
  53. {
  54. Proc proc;
  55. SlotState state;
  56. union {
  57. uint8_t count; //为0时表示回调函数未被调用或回调函数已经返回
  58. uint32_t placeholder;
  59. };
  60. uint32_t cost;
  61. };
  62. int m_numberMax;
  63. int m_number;
  64. SignalSlot* m_slots;
  65. CMutex m_mutex;
  66. int m_threadId;
  67. bool m_stat;
  68. public:
  69. /// 构造函数
  70. /// \param maxSlots 能够连接的最大函数指针对象的个数
  71. SIGNAL_SIGNAL(int maxSlots) :
  72. m_numberMax(maxSlots), m_number(0), m_threadId(-1),m_stat(false)
  73. {
  74. m_slots = new SignalSlot[maxSlots];
  75. for(int i = 0; i < m_numberMax; i++)
  76. {
  77. m_slots[i].state = slotStateEmpty;
  78. m_slots[i].placeholder = 0;
  79. m_slots[i].count = 0;
  80. }
  81. }
  82. /// 析构函数
  83. ~SIGNAL_SIGNAL()
  84. {
  85. delete []m_slots;
  86. }
  87. /// 挂载函数指针对象
  88. /// \param proc 函数指针对象
  89. /// \param position 对象挂载位置
  90. /// \retval >=0 调用后已经挂载到信号的函数指针对象个数
  91. /// \retval <0 errorCode类型的错误码
  92. int attach(const Proc &proc, SlotPosition position = any)
  93. {
  94. int i;
  95. if(!proc)
  96. {
  97. return errorEmptyProc;
  98. }
  99. if(isAttached(proc))
  100. {
  101. return errorExist;
  102. }
  103. CGuard guard(m_mutex);
  104. switch(position)
  105. {
  106. case any:
  107. for(i = 0; i < m_numberMax; i++)
  108. {
  109. if(m_slots[i].state == slotStateEmpty)
  110. {
  111. m_slots[i].proc = proc;
  112. m_slots[i].state = slotStateNormal;
  113. return ++m_number;
  114. }
  115. }
  116. break;
  117. case back:
  118. for(i = m_numberMax - 1; i >= 0; i--)
  119. {
  120. if(m_slots[i].state == slotStateEmpty)
  121. {
  122. for(int j = i; j < m_numberMax - 1; j++)
  123. {
  124. m_slots[j] = m_slots[j + 1];
  125. }
  126. m_slots[m_numberMax - 1].proc = proc;
  127. m_slots[m_numberMax - 1].state = slotStateNormal;
  128. return ++m_number;
  129. }
  130. }
  131. break;
  132. case front:
  133. for(i = 0; i < m_numberMax; i++)
  134. {
  135. if(m_slots[i].state == slotStateEmpty)
  136. {
  137. for(int j = i; j > 0; j--)
  138. {
  139. m_slots[j] = m_slots[j - 1];
  140. }
  141. m_slots[0].proc = proc;
  142. m_slots[0].state = slotStateNormal;
  143. return ++m_number;
  144. }
  145. }
  146. break;
  147. }
  148. return errorFull;
  149. }
  150. /// 卸载函数指针对象,根据对象中保存的函数指针来匹配。
  151. /// \param proc 函数指针对象
  152. /// \param wait 是否等待正在进行的回调结束。一般在使用者对象析构的时候需要等待,
  153. /// 如果是在回调函数里卸载,则不能等待。等待要特别小心,防止死锁.
  154. /// \retval >=0 调用后已经挂载到信号的函数指针对象个数
  155. /// \retval <0 errorCode类型的错误码
  156. int detach(const Proc &proc, bool wait = false)
  157. {
  158. if (!proc)
  159. {
  160. return errorEmptyProc;
  161. }
  162. CGuard guard(m_mutex);
  163. for (int i = 0; i < m_numberMax; i++)
  164. {
  165. if(m_slots[i].proc == proc
  166. && m_slots[i].state == slotStateNormal)
  167. {
  168. /// 回调线程和stop线程不是同一线程时,才需要等待,否则等待会引起自锁
  169. if(wait && m_slots[i].count && CThread::getCurrentThreadID() != m_threadId)
  170. {
  171. while(m_slots[i].count)
  172. {
  173. m_mutex.leave();
  174. CThread::sleep(10);
  175. m_mutex.enter();
  176. }
  177. }
  178. m_slots[i].state = slotStateEmpty;
  179. return --m_number;
  180. }
  181. };
  182. return errorNoFound;
  183. }
  184. /// 判断卸载函数指针对象是否挂载,根据对象中保存的函数指针来匹配。
  185. /// \param proc 函数指针对象
  186. bool isAttached(const Proc &proc)
  187. {
  188. CGuard guard(m_mutex);
  189. if(!proc)
  190. {
  191. return false;
  192. }
  193. for(int i = 0; i < m_numberMax; i++)
  194. {
  195. if(m_slots[i].proc == proc
  196. && m_slots[i].state == slotStateNormal)
  197. {
  198. return true;
  199. }
  200. }
  201. return false;
  202. }
  203. /// 重载()运算符,可以以函数对象的形式来调用连接到信号的所有函数指针。
  204. inline void operator()(SIGNAL_TYPE_ARGS)
  205. {
  206. CGuard guard(m_mutex);
  207. uint64_t us1 = 0, us2 = 0;
  208. m_threadId = CThread::getCurrentThreadID(); // 保存回调线程ID
  209. for(int i = 0; i < m_numberMax; i++) // call back functions one by one
  210. {
  211. if(m_slots[i].state == slotStateNormal)
  212. {
  213. Proc temp = m_slots[i].proc;
  214. m_slots[i].count++;
  215. m_mutex.leave();
  216. // 函数执行与性能统计
  217. if(m_stat)
  218. us1 = CTime::getCurrentMicroSecond();
  219. temp(SIGNAL_ARGS);
  220. if(m_stat)
  221. {
  222. us2 = CTime::getCurrentMicroSecond();
  223. m_slots[i].cost = (us1 <= us2) ? uint32_t(us2 - us1) : 1;
  224. }
  225. m_mutex.enter();
  226. m_slots[i].count--;
  227. }
  228. }
  229. }
  230. void stat()
  231. {
  232. int i;
  233. CGuard guard(m_mutex);
  234. for(i = 0; i < m_numberMax; i++)
  235. {
  236. if(m_slots[i].state == slotStateNormal)
  237. {
  238. printf("\t%8d us\n", m_slots[i].cost);
  239. }
  240. }
  241. }
  242. void enableStat(bool enable=true)
  243. {
  244. m_stat = enable;
  245. }
  246. };
  247. #undef SIGNAL_SIGNAL
  248. #undef FUNCTION_FUNCTION