SpTimer.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #include "stdafx.h"
  2. #include "SpBase.h"
  3. #include "SpEntity.h"
  4. #include "SpModule.h"
  5. #include "SpTimer.h"
  6. #include "SpMisc.h"
  7. #include "gettimeofday.h"
  8. #include "list.h"
  9. #include "spinlock.h"
  10. #include "memutil.h"
  11. #include "refcnt.h"
  12. //#include "hash.h"
  13. //#include "hashset.h"
  14. //#include "jhash.h"
  15. #include "sp_svc.h"
  16. #include "sp_dbg_export.h"
  17. #include "sp_tmr.h"
  18. #ifdef _WIN32
  19. #include "sp_checkEntity.h"
  20. #endif //_WIN32
  21. #include "dbgutil.h"
  22. struct SpTimer_key_t
  23. {
  24. DWORD dwTimerID;
  25. };
  26. struct SpTimer
  27. {
  28. struct hlist_node hentry;
  29. DWORD dwInterval;
  30. SpTimer_key_t key;
  31. SpEntity *pEntity;
  32. volatile LONG lStop;
  33. IReleasable *pUserData;
  34. ITimerListener *pListener;
  35. struct timeval tmNext;
  36. sp_tmr_t *tmr;
  37. SpTimerList *pList;
  38. spinlock_t lock;
  39. DECLARE_REF_COUNT_MEMBER(iRefCount);
  40. };
  41. struct SpTimerList
  42. {
  43. SpEntity *pEntity;
  44. spinlock_t lock;
  45. htable_t *ht_timer;
  46. };
  47. static __inline unsigned int timer_key_hasher(const SpTimer_key_t *key)
  48. {
  49. return key->dwTimerID;
  50. }
  51. static __inline int timer_key_cmp(const SpTimer_key_t *key1, const SpTimer_key_t *key2)
  52. {
  53. return (int)key1->dwTimerID - (int)key2->dwTimerID;
  54. }
  55. IMPLEMENT_HTABLE_STATIC(timer, SpTimer_key_t, SpTimer, key, hentry, timer_key_hasher, timer_key_cmp)
  56. static void __SpTimerDestroy(SpTimer *pTimer)
  57. {
  58. sp_tmr_destroy(pTimer->tmr);
  59. if (pTimer->pUserData) {
  60. delete pTimer->pUserData;
  61. pTimer->pUserData = NULL;
  62. }
  63. pTimer->tmr = NULL;
  64. }
  65. IMPLEMENT_REF_COUNT_MT_STATIC(SpTimer, SpTimer, iRefCount, __SpTimerDestroy)
  66. static void tmr_callback(sp_tmr_t *timer, int err, void *user_data)
  67. {
  68. SpTimer *pTimer = (SpTimer *)user_data;
  69. if (!err && !pTimer->lStop) {
  70. #ifdef _WIN32
  71. getEntityResource()->m_Entity = pTimer->pList->pEntity;
  72. #else
  73. GetSpModule()->SetThreadEntity(pTimer->pList->pEntity);
  74. #endif //_WIN32
  75. pTimer->pListener->OnTimeout(pTimer->key.dwTimerID); // OnTimeout()
  76. spinlock_enter(&pTimer->lock, -1);
  77. if (!pTimer->lStop) { /* user may cancel in callback function */
  78. unsigned int delay;
  79. struct timeval now;
  80. gettimeofday(&pTimer->tmNext, NULL); // 以当前时间重置定时器,防止修改系统时间造成死循环
  81. timeval_add_msec(&pTimer->tmNext, pTimer->dwInterval);
  82. /*gettimeofday(&now, NULL);
  83. if (timeval_cmp(&now, &pTimer->tmNext) >= 0) {
  84. delay = 0;
  85. } else {
  86. delay = timeval_sub(&pTimer->tmNext, &now);
  87. }*/
  88. delay = pTimer->dwInterval;
  89. SpTimer_inc_ref(pTimer);
  90. int rc = sp_tmr_schedule(timer, delay);
  91. if (rc != 0) {
  92. SpTimer_dec_ref(pTimer);
  93. DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("internal schedule timer failed!");
  94. }
  95. }
  96. spinlock_leave(&pTimer->lock);
  97. }
  98. SpTimer_dec_ref(pTimer);
  99. }
  100. SpTimer *SpTimerCreate(SpTimerList *pList, DWORD dwTimerID, DWORD dwInterval, ITimerListener *pListener)
  101. {
  102. sp_svc_t *svc;
  103. SpTimer *pTimer = MALLOC_T(SpTimer);
  104. int rc;
  105. sp_tmr_callback cb;
  106. svc = (sp_svc_t*)pList->pEntity->get_svc();
  107. INIT_HLIST_NODE(&pTimer->hentry);
  108. pTimer->pList = pList;
  109. pTimer->pEntity = pList->pEntity;
  110. pTimer->dwInterval = dwInterval;
  111. pTimer->key.dwTimerID = dwTimerID;
  112. pTimer->pListener = pListener;
  113. pTimer->pUserData = NULL;
  114. cb.user_data = pTimer;
  115. cb.on_timer = &tmr_callback;
  116. cb.on_destroy = NULL;
  117. rc = sp_tmr_create(sp_svc_get_tmr_mgr(svc), NULL, &cb, &pTimer->tmr);
  118. if (rc != 0) {
  119. DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("create internal tmr failed!");
  120. free(pTimer);
  121. return NULL;
  122. }
  123. spinlock_init(&pTimer->lock);
  124. REF_COUNT_INIT(&pTimer->iRefCount);
  125. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("SpTimer created dwTimerId = %d, dwInterval=%d", dwTimerID, dwInterval);
  126. return pTimer;
  127. }
  128. void SpTimerDestroy(SpTimer *pTimer)
  129. {
  130. SpTimer_dec_ref(pTimer);
  131. }
  132. void SpTimerSetUserData(SpTimer *pTimer, IReleasable *pUserData)
  133. {
  134. pTimer->pUserData = pUserData;
  135. }
  136. void SpTimerGetUserData(SpTimer *pTimer, CSmartPointer<IReleasable> &pUserData)
  137. {
  138. pUserData.Attach(pTimer->pUserData);
  139. pTimer->pUserData = NULL;
  140. }
  141. ErrorCodeEnum SpTimerStart(SpTimer *pTimer)
  142. {
  143. int rc;
  144. pTimer->lStop = 0;
  145. sp_svc_t* svc = static_cast<sp_svc_t*>(pTimer->pList->pEntity->get_svc());
  146. gettimeofday(&pTimer->tmNext, NULL);
  147. timeval_add_msec(&pTimer->tmNext, pTimer->dwInterval);
  148. SpTimer_inc_ref(pTimer);
  149. #ifdef _WIN32
  150. getEntityResource()->m_timer = pTimer;
  151. #endif //_WIN32
  152. rc = sp_tmr_schedule(pTimer->tmr, pTimer->dwInterval);
  153. if (rc != 0) {
  154. SpTimer_dec_ref(pTimer);
  155. sp_tmr_destroy(pTimer->tmr);
  156. pTimer->tmr = NULL;
  157. return SpTranslateError(rc);
  158. }
  159. return Error_Succeed;
  160. }
  161. void SpTimerStop(SpTimer *pTimer)
  162. {
  163. if (pTimer->lStop)
  164. return;
  165. InterlockedExchange(&pTimer->lStop, 1);
  166. spinlock_enter(&pTimer->lock, -1);
  167. sp_tmr_cancel(pTimer->tmr);
  168. spinlock_leave(&pTimer->lock);
  169. }
  170. void SpTimerSetInterval(SpTimer *pTimer, DWORD dwInterval)
  171. {
  172. pTimer->dwInterval = dwInterval;
  173. }
  174. DWORD SpTimerGetInterval(SpTimer *pTimer)
  175. {
  176. return pTimer->dwInterval;
  177. }
  178. SpTimerList *SpTimerListCreate(SpEntity *pEntity)
  179. {
  180. SpTimerList *pList = MALLOC_T(SpTimerList);
  181. spinlock_init(&pList->lock);
  182. pList->ht_timer = htable_create(0);
  183. pList->pEntity = pEntity;
  184. return pList;
  185. }
  186. void SpTimerListDestroy(SpTimerList *pList)
  187. {
  188. TOOLKIT_ASSERT(pList);
  189. TOOLKIT_ASSERT(pList->ht_timer->count == 0);
  190. htable_destroy(pList->ht_timer);
  191. free(pList);
  192. }
  193. SpTimer *SpTimerListFind(SpTimerList *pList, DWORD dwTimerID)
  194. {
  195. TOOLKIT_ASSERT(pList);
  196. SpTimer_key_t key = {dwTimerID};
  197. SpTimer* pTimer = timer_find(pList->ht_timer, &key);
  198. return pTimer;
  199. }
  200. void SpTimerListAdd(SpTimerList *pList, SpTimer *pTimer)
  201. {
  202. TOOLKIT_ASSERT(pTimer);
  203. timer_add(pList->ht_timer, pTimer);
  204. }
  205. void SpTimerListRemove(SpTimerList *pList, SpTimer *pTimer)
  206. {
  207. TOOLKIT_ASSERT(pTimer);
  208. timer_remove(pList->ht_timer, pTimer);
  209. }
  210. void SpTimerListLock(SpTimerList *pList)
  211. {
  212. TOOLKIT_ASSERT(pList);
  213. spinlock_enter(&pList->lock, -1);
  214. }
  215. void SpTimerListUnlock(SpTimerList *pList)
  216. {
  217. TOOLKIT_ASSERT(pList);
  218. spinlock_leave(&pList->lock);
  219. }
  220. void SpTimerListStopAll(SpTimerList *pList)
  221. {
  222. for (int i = 0; i < pList->ht_timer->size; ++i) {
  223. SpTimer *tpos;
  224. struct hlist_node *pos;
  225. hlist_for_each_entry(tpos, pos, &pList->ht_timer->buckets[i], SpTimer, hentry) {
  226. SpTimerStop(tpos);
  227. }
  228. }
  229. }