SpTimer.cpp 5.8 KB

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