SysCallbacks.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /** (c) Nullsoft, Inc. C O N F I D E N T I A L
  2. ** Filename:
  3. ** Project:
  4. ** Description:
  5. ** Author: Ben Allison [email protected]
  6. ** Created:
  7. **/
  8. #include "main.h"
  9. #include "SysCallbacks.h"
  10. #include <api/syscb/callbacks/syscb.h>
  11. #include "../nu/AutoLock.h"
  12. using namespace Nullsoft::Utility;
  13. SysCallbacks::SysCallbacks()
  14. {
  15. reentry=0;
  16. inCallback=false;
  17. }
  18. //note: it's OK to add in the middle of an issueCallback
  19. //because new callbacks go at the end of the list
  20. //and the lockguard prevents list corruption
  21. int SysCallbacks::syscb_registerCallback(SysCallback *cb, void *param)
  22. {
  23. AutoLock lock(callbackGuard LOCKNAME("SysCallbacks::syscb_registerCallback"));
  24. int event_type = cb->getEventType();
  25. //CallbackList *&callbacks = callback_map[event_type];
  26. //if (!callbacks)
  27. // callbacks = new CallbackList;
  28. //callbacks->push_back(cb);
  29. EventMap::iterator find = callback_map.find(event_type);
  30. CallbackList* callbacks = 0;
  31. if (find != callback_map.end())
  32. {
  33. callbacks = find->second;
  34. }
  35. else
  36. {
  37. callbacks = new CallbackList();
  38. callback_map.insert({ event_type, callbacks });
  39. }
  40. if (callbacks)
  41. {
  42. callbacks->push_back(cb);
  43. }
  44. return 1;
  45. }
  46. int SysCallbacks::syscb_deregisterCallback(SysCallback *cb)
  47. {
  48. AutoLock lock(callbackGuard LOCKNAME("SysCallbacks::syscb_deregisterCallback"));
  49. if (inCallback)
  50. deleteMeAfterCallbacks.push_back(cb);
  51. else
  52. {
  53. int event_type = cb->getEventType();
  54. EventMap::iterator find = callback_map.find(event_type);
  55. if (find != callback_map.end())
  56. {
  57. CallbackList *callbacks = find->second;
  58. if (callbacks)
  59. {
  60. //callbacks->eraseAll(cb);
  61. auto it = callbacks->begin();
  62. while ( it != callbacks->end())
  63. {
  64. if (*it != cb)
  65. {
  66. it++;
  67. continue;
  68. }
  69. it = callbacks->erase(it);
  70. }
  71. }
  72. }
  73. }
  74. return 1;
  75. }
  76. int SysCallbacks::syscb_issueCallback(int event_type, int msg, intptr_t param1 , intptr_t param2)
  77. {
  78. AutoLock lock(callbackGuard LOCKNAME("SysCallbacks::syscb_issueCallback"));
  79. reentry++;
  80. inCallback=true;
  81. EventMap::iterator find = callback_map.find(event_type);
  82. if (find != callback_map.end())
  83. {
  84. CallbackList *callbacks = find->second;
  85. if (callbacks)
  86. {
  87. for (size_t i=0;i<callbacks->size();i++)
  88. {
  89. SysCallback *callback = callbacks->at(i);
  90. //if (!deleteMeAfterCallbacks.contains(callback))
  91. // callback->notify(msg, param1, param2);
  92. bool found = false;
  93. for (auto obj : deleteMeAfterCallbacks)
  94. {
  95. if (obj == callback)
  96. {
  97. found = true;
  98. break;
  99. }
  100. }
  101. if (!found)
  102. callback->notify(msg, param1, param2);
  103. }
  104. }
  105. }
  106. inCallback=false;
  107. reentry--;
  108. if (reentry==0)
  109. {
  110. for ( SysCallback *l_sys_call_back : deleteMeAfterCallbacks )
  111. {
  112. for (EventMap::iterator itr=callback_map.begin(); itr != callback_map.end(); itr++)
  113. {
  114. CallbackList *callbacks = itr->second;
  115. if (callbacks)
  116. {
  117. //callbacks->eraseAll(cb);
  118. auto it = callbacks->begin();
  119. while (it != callbacks->end())
  120. {
  121. if (*it != l_sys_call_back )
  122. {
  123. it++;
  124. continue;
  125. }
  126. it = callbacks->erase(it);
  127. }
  128. }
  129. }
  130. }
  131. deleteMeAfterCallbacks.clear();
  132. }
  133. return 1;
  134. }
  135. SysCallback *SysCallbacks::syscb_enum(int event_type, size_t n)
  136. {
  137. AutoLock lock(callbackGuard LOCKNAME("SysCallbacks::syscb_enum"));
  138. // TODO: maybe check !deleteMeAfterCallbacks.contains(callbacks[i])
  139. if (event_type)
  140. {
  141. EventMap::iterator find = callback_map.find(event_type);
  142. if (find != callback_map.end())
  143. {
  144. CallbackList *callbacks = find->second;
  145. if (callbacks)
  146. {
  147. if (n <= callbacks->size())
  148. {
  149. SysCallback *callback = callbacks->at(n);
  150. if (callback)
  151. callback->AddRef(); // benski> don't be fooled. most objects don't actually support reference counting
  152. return callback;
  153. }
  154. }
  155. }
  156. }
  157. else
  158. {
  159. // enumerates ALL syscallbacks
  160. for (EventMap::iterator itr=callback_map.begin(); itr != callback_map.end(); itr++)
  161. {
  162. CallbackList *callbacks = itr->second;
  163. if (callbacks)
  164. {
  165. if (n >= callbacks->size())
  166. {
  167. n-=callbacks->size();
  168. }
  169. else
  170. {
  171. SysCallback *callback = callbacks->at(n);
  172. if (callback)
  173. callback->AddRef(); // benski> don't be fooled. most objects don't actually support reference counting
  174. return callback;
  175. }
  176. }
  177. }
  178. }
  179. return 0;
  180. }
  181. #define CBCLASS SysCallbacks
  182. START_DISPATCH;
  183. CB(API_SYSCB_SYSCB_REGISTERCALLBACK, syscb_registerCallback)
  184. CB(API_SYSCB_SYSCB_DEREGISTERCALLBACK, syscb_deregisterCallback)
  185. CB(API_SYSCB_SYSCB_ISSUECALLBACK, syscb_issueCallback)
  186. CB(API_SYSCB_SYSCB_ENUM, syscb_enum)
  187. END_DISPATCH;
  188. #undef CBCLASS