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