jlib.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  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. try
  39. {
  40. queryInitTable()->init(0);
  41. }
  42. catch(IException * e)
  43. {
  44. StringBuffer msg;
  45. fprintf(stderr, "Exception in initialization code: %s\n", e->errorMessage(msg).str());
  46. unsigned code = e->errorCode();
  47. _exit(code ? code : 2);
  48. }
  49. }
  50. InitTable::InitTable()
  51. {
  52. }
  53. void InitTable::init(SoContext ctx)
  54. {
  55. initializers.sort(&sortFuncDescending);
  56. ForEachItemIn(i, initializers)
  57. {
  58. InitializerType &iT = initializers.element(i);
  59. // printf("module initialization %d:%d\n", iT.modpriority, iT.priority);
  60. if (iT.soCtx == ctx && iT.state == ITS_Uninitialized && iT.initFunc)
  61. {
  62. bool res;
  63. try
  64. {
  65. res = iT.initFunc();
  66. iT.state = ITS_Initialized;
  67. }
  68. catch (...)
  69. {
  70. fprintf(stderr, "module initialization %d:%d threw exception\n", iT.modpriority,iT.priority);
  71. throw;
  72. }
  73. if (!res)
  74. {
  75. fprintf(stderr, "module initialization %d:%d failed\n", iT.modpriority,iT.priority);
  76. assertex(res);
  77. }
  78. }
  79. }
  80. }
  81. void InitTable::exit(SoContext ctx)
  82. {
  83. initializers.sort(&sortFuncDescending); // NB read in reverse so no need to sort ascending
  84. ForEachItemInRev(i, initializers)
  85. {
  86. InitializerType &iT = initializers.element(i);
  87. if (iT.soCtx == ctx)
  88. {
  89. if (iT.state == ITS_Initialized)
  90. {
  91. if (iT.modExit && iT.modExit->func)
  92. {
  93. //printf("::exit - destroying prior = %d\n", iT.priority);
  94. iT.modExit->func();
  95. iT.modExit->func = NULL;
  96. }
  97. }
  98. else
  99. {
  100. fprintf(stderr, "InitTable::exit %p state is %d\n", ctx, (int) iT.state);
  101. }
  102. initializers.remove(i);
  103. }
  104. }
  105. }
  106. int InitTable::sortFuncDescending(const InitializerType * i1, const InitializerType * i2)
  107. {
  108. int ret = i2->modpriority - i1->modpriority;
  109. return ret ? ret : i2->priority - i1->priority;
  110. }
  111. int InitTable::sortFuncAscending(InitializerType const *i1, InitializerType const *i2)
  112. {
  113. int ret = i1->modpriority - i2->modpriority;
  114. return ret ? ret : i1->priority - i2->priority;
  115. }
  116. void InitTable::add(InitializerType &iT)
  117. {
  118. initializers.append(iT);
  119. }
  120. void InitTable::add(boolFunc func, unsigned int priority, unsigned int modpriority, byte state)
  121. {
  122. InitializerType iT;
  123. iT.initFunc = func;
  124. iT.modExit = NULL;
  125. iT.priority = priority;
  126. iT.modpriority = modpriority;
  127. iT.soCtx = (SoContext)0;
  128. iT.state = state;
  129. initializers.append(iT);
  130. }
  131. DynamicScopeCtx::DynamicScopeCtx()
  132. {
  133. dynamicScopeCtx = this;
  134. }
  135. DynamicScopeCtx::~DynamicScopeCtx()
  136. {
  137. dynamicScopeCtx = NULL;
  138. }
  139. void DynamicScopeCtx::processInitialization(SoContext soCtx)
  140. {
  141. if (soCtx)
  142. {
  143. // initialize those in this context
  144. initTable.init();
  145. // add to global table with patched ctx's, for use by ExitModuleObjects(ctx) call
  146. ForEachItemIn(i, initTable.initializers)
  147. {
  148. InitializerType &iT = initTable.element(i);
  149. iT.soCtx = soCtx;
  150. queryInitTable()->add(iT);
  151. }
  152. }
  153. }
  154. ModInit::ModInit(boolFunc func, unsigned int priority, unsigned int modpriority)
  155. {
  156. InitTable *initTable = dynamicScopeCtx ? &dynamicScopeCtx->initTable : queryInitTable();
  157. #if !defined(EXPLICIT_INIT)
  158. initTable->add(NULL, priority, modpriority, ITS_Initialized);
  159. func();
  160. #else
  161. initTable->add(func, priority, modpriority);
  162. #endif
  163. }
  164. ModExit::ModExit(voidFunc _func)
  165. {
  166. // assumes modinit preceded this call
  167. InitTable *initTable = dynamicScopeCtx ? &dynamicScopeCtx->initTable : queryInitTable();
  168. assertex(initTable->items());
  169. func = _func;
  170. InitializerType &iT = initTable->initializers.last();
  171. assertex(!iT.modExit);
  172. iT.modExit = this;
  173. }
  174. #if !defined(EXPLICIT_INIT)
  175. ModExit::~ModExit()
  176. {
  177. if (_initTable)
  178. {
  179. if (func)
  180. {
  181. try { func(); }
  182. catch (...)
  183. {
  184. printf("Non-prioritised (ExitModuleObjects was not called) module object destruction failure. Ignoring.\n");
  185. }
  186. func = NULL;
  187. }
  188. }
  189. }
  190. #endif
  191. // check that everything compiles correctly
  192. #if 0
  193. typedef MapBetween<LinkedIInterface, IInterfacePtr, LinkedIInterface, IInterfacePtr> MapIItoII;
  194. MapIItoII map;
  195. void f(IInterface * i1, IInterface * i2)
  196. {
  197. map.setValue(i1, i2);
  198. }
  199. //==========================================================================
  200. class MappingStringToCInterface : public MappingStringTo<CInterfacePtr,CInterfacePtr>
  201. {
  202. public:
  203. MappingStringToCInterface(const char * k, CInterfacePtr a) :
  204. MappingStringTo<CInterfacePtr,CInterfacePtr>(k,a) {}
  205. ~MappingStringToCInterface() { ::Release(val); }
  206. };
  207. typedef MapStringTo<CInterfacePtr,CInterfacePtr,MappingStringToCInterface> MapStringToCInterface;
  208. void test()
  209. {
  210. MapStringToCInterface map;
  211. CInterface * temp = new CInterface;
  212. map.setValue("gavin", temp);
  213. temp->Link();
  214. map.setValue("richard", temp);
  215. map.remove("gavin");
  216. map.remove("richard");
  217. }
  218. //==========================================================================
  219. void test2(void)
  220. {
  221. MapUnsignedToInt map1;
  222. MapStrToUnsigned map2;
  223. map1.setValue(1, 2);
  224. map1.setValue(2, 3);
  225. map2.setValue("gavin",30);
  226. map2.setValue("liz",29);
  227. assertex(*map1.getValue(1) == 2);
  228. assertex(*map1.getValue(2) == 3);
  229. assertex(*map2.getValue("gavin") == 30);
  230. assertex(*map2.getValue("liz") == 29);
  231. test();
  232. };
  233. #ifndef USING_MPATROL
  234. #ifdef _WIN32
  235. #define _CRTDBG_MAP_ALLOC
  236. #include <crtdbg.h>
  237. #endif
  238. #endif
  239. int main(int argc, const char **argv)
  240. {
  241. #ifdef _DEBUG
  242. #ifdef _WIN32
  243. _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
  244. _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
  245. _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
  246. _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
  247. _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
  248. _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
  249. _CrtMemState oldMemState, newMemState, diffMemState;
  250. _CrtMemCheckpoint(&oldMemState);
  251. #endif
  252. #endif
  253. test();
  254. test2();
  255. #ifdef _DEBUG
  256. #ifdef _WIN32
  257. #ifndef USING_MPATROL //using mpatrol memory leak tool
  258. _CrtMemCheckpoint(&newMemState);
  259. if(_CrtMemDifference(&diffMemState, &oldMemState, &newMemState))
  260. {
  261. _CrtMemDumpAllObjectsSince(&diffMemState);
  262. }
  263. #endif //USING_MPATROL
  264. #endif
  265. #endif
  266. return 0;
  267. }
  268. #endif