jlib.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  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()
  116. {
  117. dynamicScopeCtx = this;
  118. }
  119. DynamicScopeCtx::~DynamicScopeCtx()
  120. {
  121. dynamicScopeCtx = NULL;
  122. }
  123. void DynamicScopeCtx::processInitialization(SoContext soCtx)
  124. {
  125. if (soCtx)
  126. {
  127. // initialize those in this context
  128. initTable.init();
  129. // add to global table with patched ctx's, for use by ExitModuleObjects(ctx) call
  130. ForEachItemIn(i, initTable.initializers)
  131. {
  132. InitializerType &iT = initTable.element(i);
  133. iT.soCtx = soCtx;
  134. queryInitTable()->add(iT);
  135. }
  136. }
  137. }
  138. ModInit::ModInit(boolFunc func, unsigned int priority, unsigned int modpriority)
  139. {
  140. InitTable *initTable = dynamicScopeCtx ? &dynamicScopeCtx->initTable : queryInitTable();
  141. #if !defined(EXPLICIT_INIT)
  142. initTable->add(NULL, priority, modpriority, ITS_Initialized);
  143. func();
  144. #else
  145. initTable->add(func, priority, modpriority);
  146. #endif
  147. }
  148. ModExit::ModExit(voidFunc _func)
  149. {
  150. // assumes modinit preceded this call
  151. InitTable *initTable = dynamicScopeCtx ? &dynamicScopeCtx->initTable : queryInitTable();
  152. assertex(initTable->items());
  153. func = _func;
  154. InitializerType &iT = initTable->initializers.last();
  155. assertex(!iT.modExit);
  156. iT.modExit = this;
  157. }
  158. #if !defined(EXPLICIT_INIT)
  159. ModExit::~ModExit()
  160. {
  161. if (_initTable)
  162. {
  163. if (func)
  164. {
  165. try { func(); }
  166. catch (...)
  167. {
  168. printf("Non-prioritised (ExitModuleObjects was not called) module object destruction failure. Ignoring.\n");
  169. }
  170. func = NULL;
  171. }
  172. }
  173. }
  174. #endif
  175. // check that everything compiles correctly
  176. #if 0
  177. typedef MapBetween<LinkedIInterface, IInterfacePtr, LinkedIInterface, IInterfacePtr> MapIItoII;
  178. MapIItoII map;
  179. void f(IInterface * i1, IInterface * i2)
  180. {
  181. map.setValue(i1, i2);
  182. }
  183. //==========================================================================
  184. class MappingStringToCInterface : public MappingStringTo<CInterfacePtr,CInterfacePtr>
  185. {
  186. public:
  187. MappingStringToCInterface(const char * k, CInterfacePtr a) :
  188. MappingStringTo<CInterfacePtr,CInterfacePtr>(k,a) {}
  189. ~MappingStringToCInterface() { ::Release(val); }
  190. };
  191. typedef MapStringTo<CInterfacePtr,CInterfacePtr,MappingStringToCInterface> MapStringToCInterface;
  192. void test()
  193. {
  194. MapStringToCInterface map;
  195. CInterface * temp = new CInterface;
  196. map.setValue("gavin", temp);
  197. temp->Link();
  198. map.setValue("richard", temp);
  199. map.remove("gavin");
  200. map.remove("richard");
  201. }
  202. //==========================================================================
  203. void test2(void)
  204. {
  205. MapUnsignedToInt map1;
  206. MapStrToUnsigned map2;
  207. map1.setValue(1, 2);
  208. map1.setValue(2, 3);
  209. map2.setValue("gavin",30);
  210. map2.setValue("liz",29);
  211. assertex(*map1.getValue(1) == 2);
  212. assertex(*map1.getValue(2) == 3);
  213. assertex(*map2.getValue("gavin") == 30);
  214. assertex(*map2.getValue("liz") == 29);
  215. test();
  216. };
  217. #ifndef USING_MPATROL
  218. #ifdef _WIN32
  219. #define _CRTDBG_MAP_ALLOC
  220. #include <crtdbg.h>
  221. #endif
  222. #endif
  223. int main(int argc, const char **argv)
  224. {
  225. #ifdef _DEBUG
  226. #ifdef _WIN32
  227. _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
  228. _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
  229. _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
  230. _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
  231. _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
  232. _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
  233. _CrtMemState oldMemState, newMemState, diffMemState;
  234. _CrtMemCheckpoint(&oldMemState);
  235. #endif
  236. #endif
  237. test();
  238. test2();
  239. #ifdef _DEBUG
  240. #ifdef _WIN32
  241. #ifndef USING_MPATROL //using mpatrol memory leak tool
  242. _CrtMemCheckpoint(&newMemState);
  243. if(_CrtMemDifference(&diffMemState, &oldMemState, &newMemState))
  244. {
  245. _CrtMemDumpAllObjectsSince(&diffMemState);
  246. }
  247. #endif //USING_MPATROL
  248. #endif
  249. #endif
  250. return 0;
  251. }
  252. #endif