jlib.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "jlib.hpp"
  14. #include "jmisc.hpp"
  15. #include <assert.h>
  16. #include <time.h>
  17. static InitTable *_initTable = NULL;
  18. static DynamicScopeCtx *dynamicScopeCtx = NULL;
  19. InitTable *queryInitTable() { if (!_initTable) _initTable = new InitTable(); return _initTable; }
  20. void ExitModuleObjects(SoContext ctx)
  21. {
  22. if (_initTable)
  23. {
  24. if (ctx)
  25. _initTable->exit(ctx);
  26. else
  27. {
  28. InitTable *t = _initTable;
  29. _initTable = NULL;
  30. t->exit(ctx);
  31. delete t;
  32. }
  33. }
  34. }
  35. void ExitModuleObjects() { ExitModuleObjects(0); }
  36. void _InitModuleObjects()
  37. {
  38. queryInitTable()->init(0);
  39. }
  40. InitTable::InitTable()
  41. {
  42. }
  43. void InitTable::init(SoContext ctx)
  44. {
  45. initializers.sort(&sortFuncDescending);
  46. ForEachItemIn(i, initializers)
  47. {
  48. InitializerType &iT = initializers.element(i);
  49. // printf("module initialization %d:%d\n", iT.modpriority, iT.priority);
  50. if (iT.soCtx == ctx && iT.state == ITS_Uninitialized && iT.initFunc)
  51. {
  52. bool res;
  53. try
  54. {
  55. res = iT.initFunc();
  56. iT.state = ITS_Initialized;
  57. }
  58. catch (...)
  59. {
  60. printf("module initialization %d:%d threw exception\n", iT.modpriority,iT.priority);
  61. throw;
  62. }
  63. if (!res)
  64. {
  65. printf("module initialization %d:%d failed\n", iT.modpriority,iT.priority);
  66. assertex(res);
  67. }
  68. }
  69. }
  70. }
  71. void InitTable::exit(SoContext ctx)
  72. {
  73. initializers.sort(&sortFuncDescending); // NB read in reverse so no need to sort ascending
  74. ForEachItemInRev(i, initializers)
  75. {
  76. InitializerType &iT = initializers.element(i);
  77. if (iT.soCtx == ctx)
  78. {
  79. assertex(iT.state == ITS_Initialized);
  80. if (iT.modExit && iT.modExit->func)
  81. {
  82. //printf("::exit - destroying prior = %d\n", iT.priority);
  83. iT.modExit->func();
  84. iT.modExit->func = NULL;
  85. }
  86. initializers.remove(i);
  87. }
  88. }
  89. }
  90. int InitTable::sortFuncDescending(const InitializerType * i1, const InitializerType * i2)
  91. {
  92. int ret = i2->modpriority - i1->modpriority;
  93. return ret ? ret : i2->priority - i1->priority;
  94. }
  95. int InitTable::sortFuncAscending(InitializerType const *i1, InitializerType const *i2)
  96. {
  97. int ret = i1->modpriority - i2->modpriority;
  98. return ret ? ret : i1->priority - i2->priority;
  99. }
  100. void InitTable::add(InitializerType &iT)
  101. {
  102. initializers.append(iT);
  103. }
  104. void InitTable::add(boolFunc func, unsigned int priority, unsigned int modpriority, byte state)
  105. {
  106. InitializerType iT;
  107. iT.initFunc = func;
  108. iT.modExit = NULL;
  109. iT.priority = priority;
  110. iT.modpriority = modpriority;
  111. iT.soCtx = (SoContext)0;
  112. iT.state = state;
  113. initializers.append(iT);
  114. }
  115. DynamicScopeCtx::DynamicScopeCtx() : soCtx(0)
  116. {
  117. dynamicScopeCtx = this;
  118. }
  119. DynamicScopeCtx::~DynamicScopeCtx()
  120. {
  121. if (soCtx)
  122. {
  123. // initliaze those in this context
  124. initTable.init();
  125. // add to global table with patched ctx's, for use by ExitModuleObjects(ctx) call
  126. ForEachItemIn(i, initTable.initializers)
  127. {
  128. InitializerType &iT = initTable.element(i);
  129. iT.soCtx = soCtx;
  130. queryInitTable()->add(iT);
  131. }
  132. }
  133. dynamicScopeCtx = NULL;
  134. }
  135. ModInit::ModInit(boolFunc func, unsigned int priority, unsigned int modpriority)
  136. {
  137. InitTable *initTable = dynamicScopeCtx ? &dynamicScopeCtx->initTable : queryInitTable();
  138. #if !defined(EXPLICIT_INIT)
  139. initTable->add(NULL, priority, modpriority, ITS_Initialized);
  140. func();
  141. #else
  142. initTable->add(func, priority, modpriority);
  143. #endif
  144. }
  145. ModExit::ModExit(voidFunc _func)
  146. {
  147. // assumes modinit preceded this call
  148. InitTable *initTable = dynamicScopeCtx ? &dynamicScopeCtx->initTable : queryInitTable();
  149. assertex(initTable->items());
  150. func = _func;
  151. InitializerType &iT = initTable->initializers.last();
  152. assertex(!iT.modExit);
  153. iT.modExit = this;
  154. }
  155. #if !defined(EXPLICIT_INIT)
  156. ModExit::~ModExit()
  157. {
  158. if (_initTable)
  159. {
  160. if (func)
  161. {
  162. try { func(); }
  163. catch (...)
  164. {
  165. printf("Non-prioritised (ExitModuleObjects was not called) module object destruction failure. Ignoring.\n");
  166. }
  167. func = NULL;
  168. }
  169. }
  170. }
  171. #endif
  172. // check that everything compiles correctly
  173. #if 0
  174. typedef MapBetween<LinkedIInterface, IInterfacePtr, LinkedIInterface, IInterfacePtr> MapIItoII;
  175. MapIItoII map;
  176. void f(IInterface * i1, IInterface * i2)
  177. {
  178. map.setValue(i1, i2);
  179. }
  180. //==========================================================================
  181. class MappingStringToCInterface : public MappingStringTo<CInterfacePtr,CInterfacePtr>
  182. {
  183. public:
  184. MappingStringToCInterface(const char * k, CInterfacePtr a) :
  185. MappingStringTo<CInterfacePtr,CInterfacePtr>(k,a) {}
  186. ~MappingStringToCInterface() { ::Release(val); }
  187. };
  188. typedef MapStringTo<CInterfacePtr,CInterfacePtr,MappingStringToCInterface> MapStringToCInterface;
  189. void test()
  190. {
  191. MapStringToCInterface map;
  192. CInterface * temp = new CInterface;
  193. map.setValue("gavin", temp);
  194. temp->Link();
  195. map.setValue("richard", temp);
  196. map.remove("gavin");
  197. map.remove("richard");
  198. }
  199. //==========================================================================
  200. void test2(void)
  201. {
  202. MapUnsignedToInt map1;
  203. MapStrToUnsigned map2;
  204. map1.setValue(1, 2);
  205. map1.setValue(2, 3);
  206. map2.setValue("gavin",30);
  207. map2.setValue("liz",29);
  208. assertex(*map1.getValue(1) == 2);
  209. assertex(*map1.getValue(2) == 3);
  210. assertex(*map2.getValue("gavin") == 30);
  211. assertex(*map2.getValue("liz") == 29);
  212. test();
  213. };
  214. #ifndef USING_MPATROL
  215. #ifdef _WIN32
  216. #define _CRTDBG_MAP_ALLOC
  217. #include <crtdbg.h>
  218. #endif
  219. #endif
  220. int main(void)
  221. {
  222. #ifdef _DEBUG
  223. #ifdef _WIN32
  224. _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
  225. _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
  226. _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
  227. _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
  228. _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
  229. _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
  230. _CrtMemState oldMemState, newMemState, diffMemState;
  231. _CrtMemCheckpoint(&oldMemState);
  232. #endif
  233. #endif
  234. test();
  235. test2();
  236. #ifdef _DEBUG
  237. #ifdef _WIN32
  238. #ifndef USING_MPATROL //using mpatrol memory leak tool
  239. _CrtMemCheckpoint(&newMemState);
  240. if(_CrtMemDifference(&diffMemState, &oldMemState, &newMemState))
  241. {
  242. _CrtMemDumpAllObjectsSince(&diffMemState);
  243. }
  244. #endif //USING_MPATROL
  245. #endif
  246. #endif
  247. return 0;
  248. }
  249. #endif