ObjectsDeclarators.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. #include "ObjectsDeclarators.h"
  2. ObjectsDeclarators::ObjectsDeclarators() : declDesc(_FL_)
  3. {
  4. //Пока модификатор не стоит
  5. accessor = null;
  6. //Очищаем входную таблицу
  7. for(long i = 0; i < ARRSIZE(entryTable); i++)
  8. {
  9. entryTable[i] = null;
  10. }
  11. needUpdateHash = true;
  12. }
  13. ObjectsDeclarators::~ObjectsDeclarators()
  14. {
  15. }
  16. void ObjectsDeclarators::Release()
  17. {
  18. //Удаляем объекты в прямом порядке
  19. objects.ToFirst();
  20. while(true)
  21. {
  22. RegObject * pnt = objects.Get();
  23. if(!pnt) break;
  24. if(accessor->GetServiceFlag(pnt))
  25. {
  26. objects.Next();
  27. }else{
  28. delete pnt;
  29. objects.ToFirst();
  30. }
  31. }
  32. //Вызываем функцию перед удалением сервисов
  33. RegObject * pnt = null;
  34. for(objects.ToLast(); pnt = objects.Get(); objects.Prev())
  35. {
  36. Assert(accessor->GetServiceFlag(pnt));
  37. ((Service *)pnt)->PreRelease();
  38. }
  39. //Удаляем сервисы в обратном
  40. objects.ToLast();
  41. while(pnt = objects.Get())
  42. {
  43. Assert(accessor->GetServiceFlag(pnt));
  44. delete pnt;
  45. objects.ToLast();
  46. }
  47. }
  48. void ObjectsDeclarators::SetAccessor(RegistryKeyAccessor * _accessor)
  49. {
  50. accessor = _accessor;
  51. }
  52. //-------------------------------------------------------------------------------------------------------
  53. //Работа с менеджером деклараторов
  54. //-------------------------------------------------------------------------------------------------------
  55. //Добавить список деклараторов
  56. void ObjectsDeclarators::AddDecls(StormEngine_Declarator * first)
  57. {
  58. if(!first) return;
  59. //Проверяем, если первый есть в списке, то пропустим добавления
  60. for(dword i = 0; i < declDesc.Size(); i++)
  61. {
  62. if(declDesc[i].decl == first)
  63. {
  64. return;
  65. }
  66. }
  67. //Добавляем цепочку
  68. DeclDesc desc;
  69. desc.next = null;
  70. for(StormEngine_Declarator * dcl = first; dcl; dcl = dcl->GetNext())
  71. {
  72. dword i = declDesc.Add();
  73. declDesc[i].decl = dcl;
  74. declDesc[i].hash = string::HashNoCase(dcl->ClassName());
  75. declDesc[i].next = null;
  76. declDesc[i].index = i;
  77. }
  78. needUpdateHash = true;
  79. }
  80. //Построить хэшь-таблицу по деклараторам
  81. void ObjectsDeclarators::BuildHashTable()
  82. {
  83. if(!needUpdateHash) return;
  84. //Обнуляем входную таблицу
  85. for(dword i = 0; i < ARRSIZE(entryTable); i++)
  86. {
  87. entryTable[i] = null;
  88. }
  89. //Разрываем цепочки
  90. DeclDesc * declDescPtr = declDesc.GetBuffer();
  91. dword count = declDesc.Size();
  92. for(dword i = 0; i < count; i++)
  93. {
  94. declDescPtr[i].next = null;
  95. }
  96. //Строим заново хэшь-таблицу
  97. for(dword i = 0; i < count; i++)
  98. {
  99. DeclDesc & cur = declDescPtr[i];
  100. dword index = cur.hash & (ARRSIZE(entryTable) - 1);
  101. if(entryTable[index])
  102. {
  103. DeclDesc * desc = entryTable[index];
  104. while(true)
  105. {
  106. if(desc->hash == cur.hash)
  107. {
  108. if(string::IsEqual(desc->decl->ClassName(), cur.decl->ClassName()))
  109. {
  110. CoreLogOut("Game init error! Repeat class name: \"%s\" <-> \"%s\"\nTry check modules for fix problem.", desc->decl->ClassName(), cur.decl->ClassName());
  111. Sleep(1);
  112. throw "invalidate module(s)";
  113. }
  114. }
  115. if(!desc->next)
  116. {
  117. break;
  118. }
  119. desc = desc->next;
  120. }
  121. desc->next = &cur;
  122. }else{
  123. entryTable[index] = &cur;
  124. }
  125. }
  126. needUpdateHash = false;
  127. }
  128. //Создать объект по имени
  129. RegObject * ObjectsDeclarators::CreateObject(const char * name, bool isCreateService)
  130. {
  131. if(!name || !name[0])
  132. {
  133. return null;
  134. }
  135. if(needUpdateHash)
  136. {
  137. BuildHashTable();
  138. }
  139. //Найдём описание
  140. dword hash = string::HashNoCase(name);
  141. dword index = hash & (ARRSIZE(entryTable) - 1);
  142. for(DeclDesc * desc = entryTable[index]; desc; desc = desc->next)
  143. {
  144. if(desc->hash == hash)
  145. {
  146. if(string::IsEqual(desc->decl->ClassName(), name))
  147. {
  148. break;
  149. }
  150. }
  151. }
  152. if(!desc)
  153. {
  154. return null;
  155. }
  156. //Если сервис, то его создаём всего 1 раз
  157. if(desc->decl->IsService())
  158. {
  159. desc->objects.ToFirst();
  160. RegObject * obj = desc->objects.Get();
  161. if(obj)
  162. {
  163. return obj;
  164. }
  165. }
  166. //Если желаемое не совпадает с дествительным...
  167. if(desc->decl->IsService() && !isCreateService) return null;
  168. //Есть описание, пробуем создать объект
  169. RegObject * obj = desc->decl->Create();
  170. if(!obj)
  171. {
  172. return null;
  173. }
  174. //Формируем запись для быстрого поиска
  175. accessor->Reset(obj);
  176. accessor->SetGlobalIndex(obj, objects.Add(obj));
  177. accessor->SetObjectIndex(obj, desc->objects.Add(obj));
  178. accessor->SetRegIndex(obj, desc->index);
  179. accessor->SetRegistryFlag(obj);
  180. if(desc->decl->IsService()) accessor->SetServiceFlag(obj);
  181. //Инициализируем объект
  182. if(!obj->Init())
  183. {
  184. delete obj;
  185. return null;
  186. }
  187. /*
  188. //!!! отладка
  189. dword count = 0;
  190. dword hits = 0;
  191. for(objects.ToFirst(); objects.Get(); objects.Next())
  192. {
  193. if(objects.Get() == obj)
  194. {
  195. Assert(!count);
  196. count++;
  197. continue;
  198. }
  199. if(accessor->GetRegistryKey(objects.Get()) == accessor->GetRegistryKey(obj))
  200. {
  201. hits++;
  202. }
  203. }
  204. Assert(objects.Test(obj, accessor->GetGlobalIndex(obj), accessor->GetGlobalIndexStep()));
  205. Assert(count == 1);
  206. */
  207. return obj;
  208. }
  209. //Удалить объект из списков
  210. void ObjectsDeclarators::RemoveObject(RegObject * obj)
  211. {
  212. //Получаем регистрационное значение
  213. Assert(accessor->IsValidate(obj));
  214. //Если записи здесь нет, то не обрабатываем удаление
  215. if(!accessor->GetRegistryFlag(obj)) return;
  216. //!!! отладка
  217. /*
  218. dword count = 0;
  219. for(objects.ToFirst(); objects.Get(); objects.Next())
  220. {
  221. if(objects.Get() == obj)
  222. {
  223. Assert(!count);
  224. count++;
  225. continue;
  226. }
  227. Assert(accessor->GetRegistryKey(objects.Get()) != accessor->GetRegistryKey(obj));
  228. }
  229. Assert(count == 1);
  230. */
  231. //Удаляем запись из глобального списка
  232. objects.Del(obj, accessor->GetGlobalIndex(obj), accessor->GetGlobalIndexStep());
  233. //Удаляем запись из описателя
  234. dword descIndex = accessor->GetRegIndex(obj);
  235. dword objsIndex = accessor->GetObjectIndex(obj);
  236. while(true)
  237. {
  238. if(declDesc[descIndex].objects.Del(obj, objsIndex, accessor->GetObjectIndexStep()))
  239. {
  240. return;
  241. }
  242. descIndex += accessor->GetRegIndexStep();
  243. }
  244. accessor->InvalidateKey(obj);
  245. }
  246. //Найти в объекты с заданным типом
  247. ObjectsDeclarators::RegList * ObjectsDeclarators::Find(const char * name)
  248. {
  249. //Найдём описание
  250. dword hash = string::HashNoCase(name);
  251. dword index = hash & (ARRSIZE(entryTable) - 1);
  252. for(DeclDesc * desc = entryTable[index]; desc; desc = desc->next)
  253. {
  254. if(desc->hash == hash)
  255. {
  256. if(strcmp(desc->decl->ClassName(), name) == 0)
  257. {
  258. break;
  259. }
  260. }
  261. }
  262. if(!desc) return null;
  263. return &desc->objects;
  264. }
  265. //Получить список всех зарегестрированных объектов
  266. void ObjectsDeclarators::GetRegistryObjectsList(array<string> & objects)
  267. {
  268. objects.DelAll();
  269. for(long i = 0; i < declDesc; i++)
  270. {
  271. if(declDesc[i].decl->IsService()) continue;
  272. objects[objects.Add()] = declDesc[i].decl->ClassName();
  273. }
  274. }
  275. //Создать все сервисы
  276. bool ObjectsDeclarators::CreateServices()
  277. {
  278. long errorCreationIndex = -1;
  279. array<ServiceInfo> services(_FL_, 256);
  280. for(long i = 0; i < declDesc; i++)
  281. {
  282. if(!declDesc[i].decl->IsService()) continue;
  283. long level = declDesc[i].decl->Level();
  284. for(long j = 0; j < services; j++)
  285. {
  286. if(level < services[j].decl->Level()) break;
  287. }
  288. ServiceInfo si;
  289. si.decl = declDesc[i].decl;
  290. si.creationTime = -1;
  291. services.Insert(si, (dword)j);
  292. }
  293. DWORD totalCreateTime = GetTickCount();
  294. for(long i = 0; i < services; i++)
  295. {
  296. DWORD startCreateTime = GetTickCount();
  297. if(!CreateObject(services[i].decl->ClassName(), true))
  298. {
  299. CoreLogOut("\n\n\n\n\nGame init error! Can't create service \"%s\"\n\n\n\n\n", services[i].decl->ClassName());
  300. errorCreationIndex = i;
  301. break;
  302. }
  303. DWORD endCreateTime = GetTickCount();
  304. services[i].creationTime = endCreateTime - startCreateTime;
  305. }
  306. totalCreateTime = GetTickCount() - totalCreateTime;
  307. CoreLogOut("\n\n\n\n\nServices create statistics:\n");
  308. for(long i = 0; i < services; i++)
  309. {
  310. if(services[i].creationTime != -1)
  311. {
  312. CoreLogOut("%.3i: Service \"%s\", level = %i, ctration time = %.3fs", i, services[i].decl->ClassName(), services[i].decl->Level(), services[i].creationTime*0.001f);
  313. }else{
  314. if(i == errorCreationIndex)
  315. {
  316. CoreLogOut("%.3i*: Service \"%s\" error create and broke init chain", i, services[i].decl->ClassName());
  317. }else{
  318. CoreLogOut("%.3i: Service \"%s\" skip create", i, services[i].decl->ClassName());
  319. }
  320. }
  321. }
  322. CoreLogOut("\nTotal creation time: %.3fs\n\n\n", totalCreateTime*0.001f);
  323. return (errorCreationIndex < 0);
  324. }
  325. //-------------------------------------------------------------------------------------------------------
  326. //RegList
  327. //-------------------------------------------------------------------------------------------------------
  328. ObjectsDeclarators::RegList::RegList() : objects(_FL_)
  329. {
  330. firstFree = -1;
  331. first = -1;
  332. last = -1;
  333. current = -1;
  334. }
  335. //Добавить объект
  336. __forceinline long ObjectsDeclarators::RegList::Add(RegObject * obj)
  337. {
  338. current = -1;
  339. Assert(obj);
  340. //Резервируем элемент
  341. long i = -1;
  342. if(firstFree < 0)
  343. {
  344. i = objects.Add();
  345. }else{
  346. i = firstFree;
  347. firstFree = objects[i].next;
  348. }
  349. //Включаем в конец списка
  350. if(first < 0)
  351. {
  352. first = i;
  353. }
  354. if(last >= 0)
  355. {
  356. objects[last].next = i;
  357. }
  358. RegInfo & ri = objects[i];
  359. ri.obj = obj;
  360. ri.prev = last;
  361. ri.next = -1;
  362. last = i;
  363. return i;
  364. }
  365. //Удалить объект из списка
  366. __forceinline bool ObjectsDeclarators::RegList::Del(RegObject * obj, long index, long step)
  367. {
  368. for(long i = index; i < objects; i += step)
  369. {
  370. if(objects[i].obj == obj)
  371. {
  372. current = i;
  373. Del();
  374. return true;
  375. }
  376. }
  377. return false;
  378. }
  379. //Проверить на правильность регистрации
  380. __forceinline bool ObjectsDeclarators::RegList::Test(RegObject * obj, long index, long step)
  381. {
  382. for(long i = index; i < objects; i += step)
  383. {
  384. if(objects[i].obj == obj)
  385. {
  386. return true;
  387. }
  388. }
  389. return false;
  390. }
  391. //Удалить объект из списка
  392. __forceinline void ObjectsDeclarators::RegList::Del()
  393. {
  394. RegInfo & ri = objects[current];
  395. long next = objects[current].next;
  396. //Исключаем из списка
  397. if(ri.prev >= 0)
  398. {
  399. objects[ri.prev].next = ri.next;
  400. }else{
  401. first = ri.next;
  402. }
  403. if(ri.next >= 0)
  404. {
  405. objects[ri.next].prev = ri.prev;
  406. }else{
  407. last = ri.prev;
  408. }
  409. //Добавляем в список свободных
  410. ri.obj = null;
  411. ri.prev = -1;
  412. ri.next = firstFree;
  413. firstFree = current;
  414. //Поправляем итератор на следующего
  415. current = next;
  416. }
  417. //Получить объект
  418. RegObject * ObjectsDeclarators::RegList::Get()
  419. {
  420. if(current < 0) return null;
  421. return objects[current].obj;
  422. }