Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

369 lines
7.7 KiB

  1. #include <tpwrap.h>
  2. #include <windows.h>
  3. class StaticTLS
  4. {
  5. public:
  6. StaticTLS() : index_(TlsAlloc()){}
  7. ~StaticTLS() { if (index_!=TLS_OUT_OF_INDEXES) TlsFree(index_); index_ = TLS_OUT_OF_INDEXES;}
  8. void * getValue(void) { return TlsGetValue(index_);}
  9. BOOL setValue(void * ptr) { return TlsSetValue(index_, ptr);}
  10. bool valid() { return index_!=TLS_OUT_OF_INDEXES;};
  11. DWORD index_;
  12. } HandlerTLS;
  13. LIST_ENTRY
  14. Dispatcher::handlerListHead_ = { &handlerListHead_, &handlerListHead_};
  15. volatile
  16. LONG Dispatcher::registeredHandlers_ = 0;
  17. bool
  18. Dispatcher::startShutDown_ = false;
  19. CriticalSection
  20. Dispatcher::handlerListLock_(NOTHROW_LOCK, 4000 & 0x80000000);
  21. EventHandler::EventHandler(void) :
  22. handlerID_(NULL), once_(0),
  23. dispatcher_(0), refCount_(1),
  24. scheduledClose_(0)
  25. { Flink = 0; Blink=0; };
  26. EventHandler::~EventHandler(void)
  27. { }
  28. HANDLE
  29. EventHandler::getHandle(void)
  30. { return INVALID_HANDLE_VALUE;}
  31. int
  32. EventHandler::handleTimeout(void)
  33. { return -1; }
  34. int
  35. EventHandler::handleEvent(void)
  36. { return -1; }
  37. void
  38. EventHandler::close(void)
  39. { return; }
  40. LONG
  41. EventHandler::AddRef(void)
  42. { return InterlockedIncrement(&refCount_); }
  43. LONG
  44. EventHandler::Release(void)
  45. { LONG newReference = InterlockedDecrement(&refCount_);
  46. if (newReference==0)
  47. delete this;
  48. return newReference;
  49. }
  50. DWORD
  51. EventHandler::getTimeOut(void)
  52. { return INFINITE; }
  53. VOID CALLBACK
  54. Dispatcher::HandleWaitOrTimerCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired )
  55. {
  56. EventHandler * handler = reinterpret_cast<EventHandler *>(lpParameter);
  57. if (startShutDown_)
  58. return;
  59. if (handler->scheduledClose_)
  60. return;
  61. assert(lpParameter!=0);
  62. assert(HandlerTLS.getValue()==0);
  63. HandlerTLS.setValue(lpParameter);
  64. int result = 0;
  65. if (TimerOrWaitFired == TRUE)
  66. result = handler->handleTimeout();
  67. else
  68. result = handler->handleEvent();
  69. if (result == -1)
  70. removeHandler(*handler);
  71. HandlerTLS.setValue(0);
  72. };
  73. int
  74. Dispatcher::registerHandler(EventHandler& eh, int flags)
  75. {
  76. assert(startShutDown_==0);
  77. assert(eh.handlerID_ == NULL);
  78. eh.type_ = EventHandler::WAIT;
  79. handlerListLock_.acquire();
  80. BOOL retVal = RegisterWaitForSingleObject(&eh.handlerID_, eh.getHandle(), HandleWaitOrTimerCallback, &eh, eh.getTimeOut(), flags);
  81. if (retVal)
  82. openHandler(&eh);
  83. handlerListLock_.release();
  84. return retVal;
  85. };
  86. int
  87. Dispatcher::registerHandlerOnce(EventHandler& eh, int flags)
  88. {
  89. assert(startShutDown_==0);
  90. assert(eh.handlerID_ == NULL);
  91. eh.type_ = EventHandler::WAIT;
  92. handlerListLock_.acquire();
  93. eh.once_ = 1;
  94. BOOL retVal = RegisterWaitForSingleObject(&eh.handlerID_, eh.getHandle(), HandleWaitOrTimerCallback, &eh, eh.getTimeOut(), flags|WT_EXECUTEONLYONCE);
  95. if (retVal)
  96. openHandler(&eh);
  97. handlerListLock_.release();
  98. return retVal;
  99. };
  100. void Dispatcher::insertTail(EventHandler *entry)
  101. {
  102. LIST_ENTRY* _EX_Blink;
  103. LIST_ENTRY* _EX_ListhandlerListHead_;
  104. _EX_ListhandlerListHead_ = &handlerListHead_;
  105. _EX_Blink = _EX_ListhandlerListHead_->Blink;
  106. entry->Flink = _EX_ListhandlerListHead_;
  107. entry->Blink = _EX_Blink;
  108. _EX_Blink->Flink = entry;
  109. _EX_ListhandlerListHead_->Blink = entry;
  110. };
  111. void Dispatcher::removeEntry(EventHandler *entry)
  112. {
  113. entry->Flink->Blink = entry->Blink;
  114. entry->Blink->Flink = entry->Flink;
  115. entry->Flink = 0;
  116. entry->Blink = 0;
  117. };
  118. void Dispatcher::openHandler(EventHandler* entry)
  119. {
  120. entry->AddRef();
  121. InterlockedIncrement(&registeredHandlers_);
  122. insertTail(entry);
  123. }
  124. void Dispatcher::closeHandler(EventHandler* entry)
  125. {
  126. handlerListLock_.acquire();
  127. removeEntry(entry);
  128. handlerListLock_.release();
  129. entry->handlerID_ = NULL;
  130. entry->close();
  131. entry->Release();
  132. InterlockedDecrement(&registeredHandlers_);
  133. };
  134. int
  135. Dispatcher::removeHandler(EventHandler& handler)
  136. {
  137. long scheduledDelete = InterlockedCompareExchange(&handler.scheduledClose_, 1, 0);
  138. if (scheduledDelete==1)
  139. return 0;
  140. assert(handler.handlerID_);
  141. if (HandlerTLS.getValue()==0)
  142. {
  143. return DeleteNotification(&handler);
  144. }
  145. else
  146. {
  147. if (PostDeleteNotification(handler)==0)
  148. InterlockedDecrement(&registeredHandlers_);
  149. }
  150. return 0;
  151. };
  152. int
  153. Dispatcher::scheduleTimer(EventHandler& eh, DWORD first, DWORD repeat, DWORD mode )
  154. {
  155. assert(startShutDown_==0);
  156. eh.type_ = EventHandler::TIMER;
  157. handlerListLock_.acquire();
  158. bool once = (repeat==0) ||( (mode & WT_EXECUTEONLYONCE) != 0);
  159. if (once)
  160. repeat = INFINITE-1;
  161. eh.once_ = once;
  162. BOOL retCode = CreateTimerQueueTimer(&eh.handlerID_, 0, TimerCallback, &eh, first, repeat, mode);
  163. if (retCode)
  164. openHandler(&eh);
  165. handlerListLock_.release();
  166. return retCode;
  167. };
  168. int
  169. Dispatcher::cancelTimer(EventHandler& handler)
  170. {
  171. long scheduledDelete = InterlockedCompareExchange(&handler.scheduledClose_, 1, 0);
  172. if (scheduledDelete==1)
  173. return 0;
  174. if (HandlerTLS.getValue()==0)
  175. {
  176. return DeleteTimer(&handler);
  177. }
  178. else
  179. {
  180. if(PostDeleteTimer(handler)==0)
  181. InterlockedDecrement(&registeredHandlers_);
  182. }
  183. return 0;
  184. };
  185. int
  186. Dispatcher::changeTimer(EventHandler& handler, DWORD first, DWORD repeat)
  187. {
  188. assert(handler.handlerID_);
  189. if (repeat==0)
  190. {
  191. repeat = INFINITE-1;
  192. handler.once_ = 1;
  193. }
  194. return ChangeTimerQueueTimer(NULL, handler.handlerID_, first, repeat);
  195. };
  196. DWORD WINAPI Dispatcher::DeleteTimer( LPVOID lpParameter)
  197. {
  198. EventHandler * ev = reinterpret_cast<EventHandler *>(lpParameter);
  199. if (DeleteTimerQueueTimer(NULL, ev->handlerID_, INVALID_HANDLE_VALUE))
  200. {
  201. closeHandler(ev);
  202. return 1;
  203. }
  204. else
  205. InterlockedDecrement(&registeredHandlers_);
  206. return 0;
  207. };
  208. DWORD WINAPI Dispatcher::DeleteNotification( LPVOID lpParameter)
  209. {
  210. EventHandler * ev = reinterpret_cast<EventHandler *>(lpParameter);
  211. if (UnregisterWaitEx(ev->handlerID_, INVALID_HANDLE_VALUE))
  212. {
  213. closeHandler(ev);
  214. return 1;
  215. }
  216. else
  217. InterlockedDecrement(&registeredHandlers_);
  218. return 0;
  219. };
  220. BOOL Dispatcher::PostDeleteNotification(EventHandler& ev)
  221. {
  222. return QueueUserWorkItem(DeleteNotification, &ev, WT_EXECUTEDEFAULT);
  223. }
  224. BOOL Dispatcher::PostDeleteTimer(EventHandler& ev)
  225. {
  226. return QueueUserWorkItem(DeleteTimer, &ev, WT_EXECUTEDEFAULT);
  227. };
  228. void CALLBACK
  229. Dispatcher::TimerCallback(void* lpParameter, BOOLEAN TimerOrWaitFired)
  230. {
  231. assert(registeredHandlers_!=0);
  232. assert(HandlerTLS.getValue()==0);
  233. assert(TimerOrWaitFired==TRUE);
  234. assert(lpParameter!=0);
  235. EventHandler * handler = reinterpret_cast<EventHandler*>(lpParameter);
  236. if (startShutDown_)
  237. return;
  238. if (handler->scheduledClose_)
  239. return;
  240. if (handler->once_)
  241. {
  242. LONG fired = InterlockedCompareExchange(&handler->once_,2,1);
  243. if (fired != 1)
  244. return;
  245. }
  246. HandlerTLS.setValue(lpParameter);
  247. int result = handler->handleTimeout();
  248. if (result == -1)
  249. cancelTimer(*handler);
  250. HandlerTLS.setValue(0);
  251. };
  252. int
  253. Dispatcher::open()
  254. { return handlerListLock_.valid() && HandlerTLS.valid(); };
  255. int Dispatcher::close()
  256. {
  257. startShutDown_ = 1;
  258. int outstandingHandlers = 0;
  259. handlerListLock_.acquire();
  260. LIST_ENTRY * p = &handlerListHead_;
  261. LIST_ENTRY * next = p->Flink;
  262. int entries = 0;
  263. while((p = next) != &handlerListHead_)
  264. {
  265. next = next->Flink;
  266. EventHandler * ev = static_cast<EventHandler *>(p);
  267. long scheduledDelete = InterlockedCompareExchange(&ev->scheduledClose_, 1, 0);
  268. if (!scheduledDelete)
  269. {
  270. if (ev->type_==EventHandler::WAIT)
  271. DeleteNotification(ev);
  272. else
  273. DeleteTimer(ev);
  274. }
  275. }
  276. handlerListLock_.release();
  277. while(0!=registeredHandlers_)
  278. if (!SwitchToThread())
  279. Sleep(1);
  280. p = &handlerListHead_;
  281. next = p->Flink;
  282. while((p = next) != &handlerListHead_)
  283. {
  284. BOOL ret;
  285. next = next->Flink;
  286. EventHandler * ev = static_cast<EventHandler *>(p);
  287. if (ev->type_==EventHandler::WAIT)
  288. ret = UnregisterWaitEx(ev->handlerID_, INVALID_HANDLE_VALUE);
  289. else
  290. ret = DeleteTimerQueueTimer(NULL, ev->handlerID_, INVALID_HANDLE_VALUE);
  291. if (ret)
  292. {
  293. ev->close();
  294. ev->Release();
  295. }
  296. }
  297. startShutDown_ = 0;
  298. return 0;
  299. };