Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2055 lines
53 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. svsutil.hxx
  5. Abstract:
  6. Miscellaneous useful utilities header
  7. Author:
  8. Sergey Solyanik (SergeyS)
  9. --*/
  10. #if ! defined (__svsutil_HXX__)
  11. #define __svsutil_HXX__ 1
  12. #include <tchar.h>
  13. #if ! defined (UNDER_CE)
  14. #include <wchar.h>
  15. #include <stddef.h>
  16. #endif
  17. #if ! defined (TRUE)
  18. #define TRUE (1==1)
  19. #endif
  20. #if ! defined (FALSE)
  21. #define FALSE (1==2)
  22. #endif
  23. #if defined (_DEBUG) || defined (DEBUG)
  24. #define SVSUTIL_DEBUG_ANY 1
  25. #define SVSUTIL_DEBUG_TREE 1
  26. #define SVSUTIL_DEBUG_QUEUE 1
  27. #define SVSUTIL_DEBUG_STACK 1
  28. #define SVSUTIL_DEBUG_HEAP 1
  29. #define SVSUTIL_DEBUG_ARRAYS 1
  30. #define SVSUTIL_DEBUG_MT 1
  31. #define SVSUTIL_DEBUG_THREADS 1
  32. #endif
  33. #if defined (SVSUTIL_DEBUG_ANY)
  34. #define SVSUTIL_ASSERT(c) ((c)? TRUE : (svsutil_AssertBroken (TEXT(__FILE__), __LINE__), TRUE))
  35. #else
  36. #define SVSUTIL_ASSERT(c)
  37. #endif
  38. #define SVSUTIL_MAX_ALIGNMENT 8
  39. #define SVSUTIL_COLOR_BLACK 0
  40. #define SVSUTIL_COLOR_RED 1
  41. #define SVSUTIL_TREE_INITIAL 20
  42. #define SVSUTIL_QUEUE_INITIAL 20
  43. #define SVSUTIL_STACK_INITIAL 20
  44. #define SVSUTIL_ATIMER_INCR 10
  45. #if defined (SVSUTIL_DEBUG_ARRAYS)
  46. #define SVSUTIL_TIER_COLLECTION_BIT 2
  47. #define SVSUTIL_TIER_ELEMENT_BIT 3
  48. #else
  49. #define SVSUTIL_TIER_COLLECTION_BIT 6
  50. #define SVSUTIL_TIER_ELEMENT_BIT 5
  51. #endif
  52. #define SVSUTIL_TIER_COLLECTION_SIZE (1 << SVSUTIL_TIER_COLLECTION_BIT)
  53. #define SVSUTIL_TIER_ELEMENT_SIZE (1 << SVSUTIL_TIER_ELEMENT_BIT)
  54. #define SVSUTIL_TIER_COLLECTION_MASK ((~((-1) << SVSUTIL_TIER_COLLECTION_BIT)) << SVSUTIL_TIER_ELEMENT_BIT)
  55. #define SVSUTIL_TIER_ELEMENT_MASK (~((-1) << SVSUTIL_TIER_ELEMENT_BIT))
  56. #define SVSUTIL_TIER_MASK (SVSUTIL_TIER_COLLECTION_MASK | SVSUTIL_TIER_ELEMENT_MASK)
  57. #define SVSUTIL_TIER_BIT (SVSUTIL_TIER_COLLECTION_BIT + SVSUTIL_TIER_ELEMENT_BIT)
  58. #define SVSUTIL_ARRLEN(array) (sizeof(array)/sizeof(array[0]))
  59. #define SVSUTIL_CONSTSTRLEN(string) (SVSUTIL_ARRLEN((string)) - 1) // Do not count trailing '\0'
  60. #define SVSUTIL_HANDLE_INVALID 0
  61. //
  62. // General typedefs
  63. //
  64. struct FixedMemDescr;
  65. struct HashDatabase;
  66. struct SVSTimer;
  67. struct SVSAttrTimer;
  68. #define MAXSKEY ((SVSCKey)-1)
  69. #define SORTINV(kKey) (MAXSKEY - kKey)
  70. typedef unsigned long SVSCKey; // Comparison key - this HAS to be unsigned!
  71. typedef unsigned long SVSHKey; // Hash key
  72. typedef unsigned long SVSHandle; // Handle
  73. typedef void *(*FuncAlloc)(int iSize, void *pvPrivateData);
  74. typedef void (*FuncFree)(void *pvPtr, void *pvPrivateData);
  75. typedef int (*FuncDebugOut)(void *pvPtr, TCHAR *lpszFormat, ...);
  76. #if defined (__cplusplus)
  77. extern "C" {
  78. #endif
  79. //
  80. // Externs
  81. //
  82. extern FuncAlloc g_funcAlloc;
  83. extern FuncFree g_funcFree;
  84. extern FuncDebugOut g_funcDebugOut;
  85. extern void *g_pvAllocData;
  86. extern void *g_pvFreeData;
  87. extern void *g_pvDebugData;
  88. //
  89. // Prototypes and classes
  90. //
  91. void svsutil_Initialize (void);
  92. void *svsutil_Alloc (int iSize, void *pvData);
  93. void svsutil_Free (void *pvPtr, void *pvData);
  94. unsigned int svsutil_TotalAlloc (void);
  95. int svsutil_AssertBroken (TCHAR *lpszFile, int iLine);
  96. void svsutil_SetAlloc (FuncAlloc a_funcAlloc, FuncFree a_funcFree);
  97. void svsutil_SetAllocData (void *a_pvAllocData, void *a_pvFreeData);
  98. void svsutil_SetDebugOut (FuncDebugOut a_funcDebugOut, void *a_pvDebugData);
  99. wchar_t *svsutil_wcsdup (wchar_t *);
  100. char *svsutil_strdup (char *);
  101. #if defined (UNICODE)
  102. #define svsutil_tcsdup svsutil_wcsdup
  103. #else
  104. #define svsutil_tcsdup svsutil_strdup
  105. #endif
  106. struct FixedMemDescr *svsutil_AllocFixedMemDescr (unsigned int a_uiBlockSize, unsigned int a_uiBlockIncr);
  107. void *svsutil_GetFixed (struct FixedMemDescr *a_pfmd);
  108. void svsutil_FreeFixed (void *pvData, struct FixedMemDescr *a_pfmd);
  109. void svsutil_ReleaseFixedEmpty (struct FixedMemDescr *a_pfmd);
  110. void svsutil_ReleaseFixedNonEmpty (struct FixedMemDescr *a_pfmd);
  111. void svsutil_CompactFixed (struct FixedMemDescr *a_pfmd);
  112. int svsutil_IsFixedEmpty (struct FixedMemDescr *a_pfmd);
  113. int svsutil_FixedBlockSize (struct FixedMemDescr *a_pfmd);
  114. #if defined (_WINDOWS_) || defined (_WINDOWS_CE_)
  115. struct FixedMemDescr *svsutil_AllocFixedMemDescrSynch (unsigned int a_uiBlockSize, unsigned int a_uiBlockIncr, CRITICAL_SECTION *a_pcs);
  116. #endif
  117. struct HashDatabase *svsutil_GetStringHash (int iBuckets, int iSens);
  118. TCHAR *svsutil_StringHashAlloc(struct HashDatabase *pdb, TCHAR *lpszString);
  119. TCHAR *svsutil_StringHashCheck (struct HashDatabase *pdb, TCHAR *lpszString);
  120. int svsutil_StringHashFree (struct HashDatabase *pdb, TCHAR *lpszString);
  121. int svsutil_StringHashRef (struct HashDatabase *pdb, TCHAR *lpszString);
  122. void svsutil_DestroyStringHash (struct HashDatabase *pdb);
  123. #if defined (SVSUTIL_DEBUG_HEAP)
  124. #define svsutil_ReleaseFixed svsutil_ReleaseFixedEmpty
  125. #else
  126. #define svsutil_ReleaseFixed svsutil_ReleaseFixedNonEmpty
  127. #endif
  128. void svsutil_GetAbsTime (unsigned int *ps, unsigned int *pms);
  129. struct SVSAttrTimer *svsutil_AllocAttrTimer (void);
  130. int svsutil_SetAttrTimer (struct SVSAttrTimer *pTimer, SVSHandle hEvent, unsigned int uiAbsTimeMillis);
  131. int svsutil_ClearAttrTimer (struct SVSAttrTimer *pTimer, SVSHandle hEvent);
  132. void svsutil_FreeAttrTimer (struct SVSAttrTimer *pTimer);
  133. void svsutil_WalkAttrTimer (struct SVSAttrTimer *pTimer, void (*pfunc)(unsigned int uiWhen, SVSHandle hEvent, void *pvArg), void *pvArg);
  134. #if defined (__cplusplus)
  135. };
  136. #endif
  137. #if defined (__cplusplus)
  138. #pragma warning(disable:4505)
  139. #if defined (_WINDOWS_) || defined (_WINDOWS_CE_) || defined (UNDER_CE)
  140. class SVSLocalCriticalSection {
  141. CRITICAL_SECTION *m_pcs;
  142. public:
  143. SVSLocalCriticalSection (CRITICAL_SECTION *pcs) {
  144. m_pcs = pcs;
  145. EnterCriticalSection (pcs);
  146. }
  147. ~SVSLocalCriticalSection (void) {
  148. LeaveCriticalSection (m_pcs);
  149. }
  150. };
  151. class SVSLocalCriticalSectionX {
  152. CRITICAL_SECTION *m_pcs;
  153. public:
  154. SVSLocalCriticalSectionX (CRITICAL_SECTION *pcs) {
  155. m_pcs = pcs;
  156. if (m_pcs)
  157. EnterCriticalSection (m_pcs);
  158. }
  159. ~SVSLocalCriticalSectionX (void) {
  160. if (m_pcs)
  161. LeaveCriticalSection (m_pcs);
  162. }
  163. };
  164. class SVSSynch {
  165. protected:
  166. CRITICAL_SECTION cs;
  167. #if defined (SVSUTIL_DEBUG_MT)
  168. int iRef;
  169. DWORD dwLockingThreadId;
  170. #endif
  171. protected:
  172. SVSSynch (void) {
  173. InitializeCriticalSection (&cs);
  174. #if defined (SVSUTIL_DEBUG_MT)
  175. iRef = 0;
  176. dwLockingThreadId = 0;
  177. #endif
  178. }
  179. ~SVSSynch (void) {
  180. #if defined (SVSUTIL_DEBUG_MT)
  181. SVSUTIL_ASSERT ((iRef == 0) && (dwLockingThreadId == 0));
  182. #endif
  183. DeleteCriticalSection (&cs);
  184. }
  185. public:
  186. void Lock (void) {
  187. EnterCriticalSection (&cs);
  188. #if defined (SVSUTIL_DEBUG_MT)
  189. DWORD dwCurrentThreadId = GetCurrentThreadId();
  190. SVSUTIL_ASSERT (((iRef == 0) && (dwLockingThreadId == 0)) || ((iRef > 0) && (dwLockingThreadId == dwCurrentThreadId)));
  191. dwLockingThreadId = dwCurrentThreadId;
  192. iRef++;
  193. #endif
  194. }
  195. void Unlock (void) {
  196. #if defined (SVSUTIL_DEBUG_MT)
  197. DWORD dwCurrentThreadId = GetCurrentThreadId ();
  198. SVSUTIL_ASSERT ((iRef > 0) && (dwLockingThreadId == dwCurrentThreadId));
  199. if (--iRef == 0)
  200. dwLockingThreadId = 0;
  201. #endif
  202. LeaveCriticalSection (&cs);
  203. }
  204. int IsLocked (void) {
  205. #if defined (SVSUTIL_DEBUG_MT)
  206. DWORD dwCurrentThreadId = GetCurrentThreadId();
  207. return (iRef > 0) && (dwLockingThreadId == dwCurrentThreadId);
  208. #else
  209. return TRUE;
  210. #endif
  211. }
  212. };
  213. #endif
  214. class SVSAllocClass {
  215. public:
  216. void *operator new (size_t iSize) {
  217. void *pRes = g_funcAlloc(iSize, g_pvAllocData);
  218. SVSUTIL_ASSERT (pRes);
  219. return pRes;
  220. }
  221. void operator delete(void *ptr) {
  222. g_funcFree (ptr, g_pvFreeData);
  223. }
  224. };
  225. class SVSRefObj {
  226. protected:
  227. int iRef;
  228. public:
  229. void AddRef (void) {
  230. #if defined (_WINDOWS_) || defined (_WINDOWS_CE_)
  231. InterlockedIncrement ((long *)&iRef);
  232. #else
  233. ++iRef;
  234. #endif
  235. }
  236. void DelRef (void) {
  237. SVSUTIL_ASSERT (iRef > 0);
  238. #if defined (_WINDOWS_) || defined (_WINDOWS_CE_)
  239. InterlockedDecrement ((long *)&iRef);
  240. #else
  241. --iRef;
  242. #endif
  243. }
  244. int GetRefCount (void) {
  245. return iRef;
  246. }
  247. SVSRefObj (void) {
  248. iRef = 1;
  249. }
  250. };
  251. class SVSSignallingRefObj : public SVSRefObj {
  252. protected:
  253. void (*pfSignal)(void *);
  254. void *pvData;
  255. public:
  256. void DelRef (void) {
  257. SVSUTIL_ASSERT (iRef > 0);
  258. #if defined (_WINDOWS_) || defined (_WINDOWS_CE_)
  259. InterlockedDecrement ((long *)&iRef);
  260. #else
  261. --iRef;
  262. #endif
  263. if ((iRef == 0) && pfSignal)
  264. pfSignal (pvData);
  265. }
  266. SVSSignallingRefObj (void) {
  267. pfSignal = NULL;
  268. pvData = NULL;
  269. }
  270. void SetSignal (void (*a_pfSignal)(void *), void *a_pvData) {
  271. SVSUTIL_ASSERT (pfSignal == NULL);
  272. SVSUTIL_ASSERT (pvData == NULL);
  273. pfSignal = a_pfSignal;
  274. pvData = a_pvData;
  275. }
  276. };
  277. //
  278. // Enumerable class
  279. //
  280. class SVSEnumClass {
  281. public:
  282. virtual SVSHandle EnumStart (void) = 0;
  283. virtual SVSHandle EnumNext (SVSHandle hEnum) = 0;
  284. virtual void *EnumGetData (SVSHandle hEnum) = 0;
  285. virtual SVSCKey EnumGetKey (SVSHandle hEnum) = 0;
  286. };
  287. //
  288. // Queue class
  289. //
  290. class SVSLinkedSegment {
  291. protected:
  292. class SVSLinkedSegment *plsNext;
  293. class SVSLinkedSegment *plsPrev;
  294. void *pvArray[1];
  295. friend class SVSQueue;
  296. friend class SVSStack;
  297. };
  298. class SVSQueue : public SVSAllocClass {
  299. protected:
  300. SVSLinkedSegment *plsHead;
  301. SVSLinkedSegment *plsTail;
  302. unsigned int iSegSize;
  303. unsigned int iBlockSize;
  304. unsigned int iHeadNdx;
  305. unsigned int iTailNdx;
  306. #if defined (SVSUTIL_DEBUG_QUEUE)
  307. void CoherencyCheck (void) {
  308. SVSUTIL_ASSERT(iSegSize > 0);
  309. SVSUTIL_ASSERT(iBlockSize > 0);
  310. SVSUTIL_ASSERT(iHeadNdx < iSegSize);
  311. SVSUTIL_ASSERT(iTailNdx < iSegSize);
  312. SVSUTIL_ASSERT (plsHead->plsNext->plsPrev == plsHead);
  313. SVSUTIL_ASSERT (plsTail->plsNext->plsPrev == plsTail);
  314. SVSUTIL_ASSERT (plsHead->plsPrev->plsNext == plsHead);
  315. SVSUTIL_ASSERT (plsTail->plsPrev->plsNext == plsTail);
  316. }
  317. #endif
  318. public:
  319. SVSQueue (unsigned int a_iSegSize = SVSUTIL_QUEUE_INITIAL) {
  320. SVSUTIL_ASSERT (a_iSegSize > 0);
  321. iSegSize = a_iSegSize;
  322. iHeadNdx = 0;
  323. iTailNdx = 0;
  324. iBlockSize = offsetof (SVSLinkedSegment, pvArray) + a_iSegSize * sizeof(void *);
  325. plsHead = plsTail = (SVSLinkedSegment *)g_funcAlloc(iBlockSize, g_pvAllocData);
  326. SVSUTIL_ASSERT (plsHead);
  327. plsHead->plsPrev = plsHead->plsNext = plsHead;
  328. #if defined (SVSUTIL_DEBUG_QUEUE)
  329. CoherencyCheck ();
  330. #endif
  331. }
  332. ~SVSQueue (void) {
  333. SVSLinkedSegment *pls = plsHead->plsNext;
  334. while (pls != plsHead) {
  335. SVSLinkedSegment *plsNext = pls->plsNext;
  336. g_funcFree (pls, g_pvFreeData);
  337. pls = plsNext;
  338. }
  339. g_funcFree (plsHead, g_pvFreeData);
  340. }
  341. int IsEmpty (void) {
  342. #if defined (SVSUTIL_DEBUG_QUEUE)
  343. CoherencyCheck ();
  344. #endif
  345. return (plsHead == plsTail) && (iHeadNdx == iTailNdx);
  346. }
  347. int Put (void *pvData) {
  348. #if defined (SVSUTIL_DEBUG_QUEUE)
  349. CoherencyCheck ();
  350. #endif
  351. plsHead->pvArray[iHeadNdx++] = pvData;
  352. if (iHeadNdx < iSegSize)
  353. return TRUE;
  354. iHeadNdx = 0;
  355. if (plsHead->plsNext != plsTail) {
  356. plsHead = plsHead->plsNext;
  357. return TRUE;
  358. }
  359. SVSLinkedSegment *pls = (SVSLinkedSegment *)g_funcAlloc(iBlockSize, g_pvAllocData);
  360. if (! pls) {
  361. SVSUTIL_ASSERT (0);
  362. iHeadNdx = iSegSize - 1;
  363. return FALSE;
  364. }
  365. pls->plsPrev = plsHead;
  366. pls->plsNext = plsTail;
  367. plsHead->plsNext = pls;
  368. plsTail->plsPrev = pls;
  369. plsHead = pls;
  370. return TRUE;
  371. }
  372. void *Peek (void) {
  373. if (IsEmpty()) {
  374. SVSUTIL_ASSERT(0);
  375. return NULL;
  376. }
  377. return plsTail->pvArray[iTailNdx];
  378. }
  379. void *Get (void) {
  380. if (IsEmpty()) {
  381. SVSUTIL_ASSERT(0);
  382. return NULL;
  383. }
  384. void *pvData = plsTail->pvArray[iTailNdx++];
  385. if (iTailNdx < iSegSize)
  386. return pvData;
  387. iTailNdx = 0;
  388. plsTail = plsTail->plsNext;
  389. return pvData;
  390. }
  391. void Compact (void) {
  392. #if defined (SVSUTIL_DEBUG_QUEUE)
  393. CoherencyCheck ();
  394. #endif
  395. SVSLinkedSegment *pls = plsHead->plsNext;
  396. while (pls != plsTail) {
  397. SVSLinkedSegment *plsNext = pls->plsNext;
  398. g_funcFree (pls, g_pvFreeData);
  399. pls = plsNext;
  400. }
  401. plsHead->plsNext = plsTail;
  402. plsTail->plsPrev = plsHead;
  403. #if defined (SVSUTIL_DEBUG_QUEUE)
  404. CoherencyCheck ();
  405. #endif
  406. }
  407. };
  408. class SVSStack : public SVSAllocClass {
  409. protected:
  410. SVSLinkedSegment *plsBase;
  411. SVSLinkedSegment *plsHead;
  412. unsigned int iSegSize;
  413. unsigned int iBlockSize;
  414. unsigned int iHeadNdx;
  415. #if defined (SVSUTIL_DEBUG_STACK)
  416. void CoherencyCheck (void) {
  417. SVSUTIL_ASSERT (iSegSize > 0);
  418. SVSUTIL_ASSERT (iBlockSize > 0);
  419. SVSUTIL_ASSERT (iHeadNdx < iSegSize);
  420. SVSUTIL_ASSERT (plsBase->plsPrev == NULL);
  421. SVSUTIL_ASSERT ((plsHead == plsBase) || (plsHead->plsPrev->plsNext == plsHead));
  422. SVSUTIL_ASSERT ((! plsHead->plsNext) || (plsHead->plsNext->plsPrev == plsHead));
  423. SVSUTIL_ASSERT ((! plsBase->plsNext) || (plsBase->plsNext->plsPrev == plsBase));
  424. }
  425. #endif
  426. public:
  427. SVSStack (unsigned int a_iSegSize = SVSUTIL_STACK_INITIAL) {
  428. SVSUTIL_ASSERT (a_iSegSize > 0);
  429. iSegSize = a_iSegSize;
  430. iHeadNdx = 0;
  431. iBlockSize = offsetof (SVSLinkedSegment, pvArray) + a_iSegSize * sizeof(void *);
  432. plsHead = plsBase = (SVSLinkedSegment *)g_funcAlloc(iBlockSize, g_pvAllocData);
  433. SVSUTIL_ASSERT (plsHead);
  434. plsHead->plsPrev = plsHead->plsNext = NULL;
  435. #if defined (SVSUTIL_DEBUG_STACK)
  436. CoherencyCheck ();
  437. #endif
  438. }
  439. ~SVSStack (void) {
  440. SVSLinkedSegment *pls = plsBase;
  441. while (pls) {
  442. SVSLinkedSegment *plsNext = pls->plsNext;
  443. g_funcFree (pls, g_pvFreeData);
  444. pls = plsNext;
  445. }
  446. }
  447. int IsEmpty (void) {
  448. #if defined (SVSUTIL_DEBUG_STACK)
  449. CoherencyCheck ();
  450. #endif
  451. return (plsHead == plsBase) && (iHeadNdx == 0);
  452. }
  453. int Push (void *pvData) {
  454. #if defined (SVSUTIL_DEBUG_STACK)
  455. CoherencyCheck ();
  456. #endif
  457. plsHead->pvArray[iHeadNdx++] = pvData;
  458. if (iHeadNdx < iSegSize)
  459. return TRUE;
  460. iHeadNdx = 0;
  461. if (plsHead->plsNext != NULL) {
  462. plsHead = plsHead->plsNext;
  463. return TRUE;
  464. }
  465. SVSLinkedSegment *pls = (SVSLinkedSegment *)g_funcAlloc(iBlockSize, g_pvAllocData);
  466. if (! pls) {
  467. SVSUTIL_ASSERT (0);
  468. iHeadNdx = iSegSize - 1;
  469. return FALSE;
  470. }
  471. pls->plsPrev = plsHead;
  472. pls->plsNext = NULL;
  473. plsHead->plsNext = pls;
  474. plsHead = pls;
  475. return TRUE;
  476. }
  477. void *Peek (void) {
  478. if (IsEmpty()) {
  479. SVSUTIL_ASSERT(0);
  480. return NULL;
  481. }
  482. int iHeadNdx2 = (int)iHeadNdx - 1;
  483. SVSLinkedSegment *plsHead2 = plsHead;
  484. if (iHeadNdx2 < 0) {
  485. iHeadNdx2 = iSegSize - 1;
  486. plsHead2 = plsHead->plsPrev;
  487. }
  488. return plsHead2->pvArray[iHeadNdx2];
  489. }
  490. void *Pop (void) {
  491. if (IsEmpty()) {
  492. SVSUTIL_ASSERT(0);
  493. return NULL;
  494. }
  495. if (((int)--iHeadNdx) < 0) {
  496. iHeadNdx = iSegSize - 1;
  497. plsHead = plsHead->plsPrev;
  498. }
  499. return plsHead->pvArray[iHeadNdx];
  500. }
  501. void Compact (void) {
  502. #if defined (SVSUTIL_DEBUG_STACK)
  503. CoherencyCheck ();
  504. #endif
  505. SVSLinkedSegment *pls = plsHead->plsNext;
  506. while (pls) {
  507. SVSLinkedSegment *plsNext = pls->plsNext;
  508. g_funcFree (pls, g_pvFreeData);
  509. pls = plsNext;
  510. }
  511. plsHead->plsNext = NULL;
  512. #if defined (SVSUTIL_DEBUG_STACK)
  513. CoherencyCheck ();
  514. #endif
  515. }
  516. };
  517. //
  518. // Expandable Arrays
  519. //
  520. template <class T> class SVSMTABlock : public SVSAllocClass {
  521. public:
  522. T **m_p_ptCollection;
  523. int m_iNdxFirst;
  524. int m_iNdxLast;
  525. SVSMTABlock *m_pNextBlock;
  526. SVSMTABlock (SVSMTABlock *a_pCurrentHead, int iStartNdx) {
  527. SVSUTIL_ASSERT ((iStartNdx & SVSUTIL_TIER_MASK) == 0);
  528. SVSUTIL_ASSERT (iStartNdx >= 0);
  529. m_pNextBlock = a_pCurrentHead;
  530. m_iNdxFirst = iStartNdx;
  531. m_iNdxLast = iStartNdx | SVSUTIL_TIER_MASK;
  532. m_p_ptCollection = NULL;
  533. }
  534. ~SVSMTABlock (void) {
  535. if (! m_p_ptCollection)
  536. return;
  537. for (int i = 0 ; i < SVSUTIL_TIER_COLLECTION_SIZE ; ++i) {
  538. if (! m_p_ptCollection[i])
  539. break;
  540. g_funcFree (m_p_ptCollection[i], g_pvFreeData);
  541. }
  542. g_funcFree (m_p_ptCollection, g_pvFreeData);
  543. }
  544. int AllocateBlock (void) {
  545. SVSUTIL_ASSERT (m_p_ptCollection == NULL);
  546. int iSz = sizeof(T *) * SVSUTIL_TIER_COLLECTION_SIZE;
  547. m_p_ptCollection = (T **)g_funcAlloc (iSz, g_pvAllocData);
  548. if (! m_p_ptCollection) {
  549. SVSUTIL_ASSERT (0);
  550. return FALSE;
  551. }
  552. memset (m_p_ptCollection, 0, iSz);
  553. return TRUE;
  554. }
  555. int AllocateCluster (int i) {
  556. SVSUTIL_ASSERT (m_p_ptCollection[i] == NULL);
  557. m_p_ptCollection[i] = (T *)g_funcAlloc(sizeof(T) * SVSUTIL_TIER_ELEMENT_SIZE, g_pvAllocData);
  558. return m_p_ptCollection[i] != NULL;
  559. }
  560. };
  561. template <class T> class SVSExpArray : public SVSAllocClass {
  562. protected:
  563. int m_iBigBlocks;
  564. int m_iPhysInLast;
  565. SVSMTABlock<T> *m_pFirstBlock;
  566. public:
  567. SVSExpArray(void) {
  568. m_pFirstBlock = NULL;
  569. m_iBigBlocks = 0;
  570. m_iPhysInLast = 0;
  571. }
  572. int SRealloc (int a_iElemNum);
  573. int CRealloc (int a_iElemNum);
  574. ~SVSExpArray(void) {
  575. while (m_pFirstBlock) {
  576. SVSMTABlock<T> *pNextBlock = m_pFirstBlock->m_pNextBlock;
  577. delete m_pFirstBlock;
  578. m_pFirstBlock = pNextBlock;
  579. }
  580. }
  581. T& operator[](int iIndex) {
  582. static T dummy;
  583. int iBaseNdx = iIndex & (~SVSUTIL_TIER_MASK);
  584. SVSMTABlock<T> *pmta = m_pFirstBlock;
  585. while (pmta) {
  586. if (pmta->m_iNdxFirst == iBaseNdx)
  587. return pmta->m_p_ptCollection[(iIndex & SVSUTIL_TIER_COLLECTION_MASK) >> SVSUTIL_TIER_ELEMENT_BIT][iIndex & SVSUTIL_TIER_ELEMENT_MASK];
  588. pmta = pmta->m_pNextBlock;
  589. }
  590. return dummy;
  591. }
  592. };
  593. template <class T> int SVSExpArray<T>::SRealloc (int a_iElemNum) {
  594. SVSUTIL_ASSERT (a_iElemNum >= 0);
  595. int iNeedBlocks = (a_iElemNum >> SVSUTIL_TIER_BIT) + 1;
  596. if (iNeedBlocks < m_iBigBlocks)
  597. return TRUE;
  598. int iClusters = ((a_iElemNum & SVSUTIL_TIER_MASK) >> SVSUTIL_TIER_ELEMENT_BIT) + 1;
  599. if ((iNeedBlocks == m_iBigBlocks) && (iClusters <= m_iPhysInLast))
  600. return TRUE;
  601. if (iNeedBlocks > m_iBigBlocks) {
  602. if (m_pFirstBlock) {
  603. while (m_iPhysInLast < SVSUTIL_TIER_COLLECTION_SIZE) {
  604. if (! m_pFirstBlock->AllocateCluster(m_iPhysInLast)) {
  605. SVSUTIL_ASSERT(0);
  606. return FALSE;
  607. }
  608. ++m_iPhysInLast;
  609. }
  610. }
  611. while (m_iBigBlocks < iNeedBlocks) {
  612. SVSMTABlock<T> *pNewFirst = new SVSMTABlock<T>(m_pFirstBlock, m_iBigBlocks << SVSUTIL_TIER_BIT);
  613. if ((! pNewFirst) || (!pNewFirst->AllocateBlock())) {
  614. SVSUTIL_ASSERT (0);
  615. return FALSE;
  616. }
  617. ++m_iBigBlocks;
  618. m_pFirstBlock = pNewFirst;
  619. m_iPhysInLast = 0;
  620. int iLimit = (m_iBigBlocks < iNeedBlocks) ? SVSUTIL_TIER_COLLECTION_SIZE : iClusters;
  621. while (m_iPhysInLast < iLimit) {
  622. if (! m_pFirstBlock->AllocateCluster(m_iPhysInLast)) {
  623. SVSUTIL_ASSERT(0);
  624. return FALSE;
  625. }
  626. ++m_iPhysInLast;
  627. }
  628. }
  629. return TRUE;
  630. }
  631. while (m_iPhysInLast < iClusters) {
  632. if (! m_pFirstBlock->AllocateCluster(m_iPhysInLast)) {
  633. SVSUTIL_ASSERT(0);
  634. return FALSE;
  635. }
  636. ++m_iPhysInLast;
  637. }
  638. return TRUE;
  639. }
  640. template <class T> int SVSExpArray<T>::CRealloc (int a_iElemNum) {
  641. SVSUTIL_ASSERT (a_iElemNum >= 0);
  642. int iNeedBlocks = (a_iElemNum >> SVSUTIL_TIER_BIT) + 1;
  643. if (iNeedBlocks > m_iBigBlocks)
  644. return SRealloc (a_iElemNum);
  645. int iClusters = ((a_iElemNum & SVSUTIL_TIER_MASK) >> SVSUTIL_TIER_ELEMENT_BIT) + 1;
  646. if ((iNeedBlocks == m_iBigBlocks) && (iClusters > m_iPhysInLast))
  647. return SRealloc (a_iElemNum);
  648. while ((iNeedBlocks > m_iBigBlocks) && (m_iBigBlocks > 0)) {
  649. SVSMTABlock<T> *pmta = m_pFirstBlock->m_pNextBlock;
  650. delete m_pFirstBlock;
  651. m_pFirstBlock = pmta;
  652. --m_iBigBlocks;
  653. m_iPhysInLast = SVSUTIL_TIER_COLLECTION_SIZE;
  654. }
  655. while (m_iPhysInLast > iClusters) {
  656. SVSUTIL_ASSERT ((m_iPhysInLast == SVSUTIL_TIER_COLLECTION_SIZE) || (! m_pFirstBlock->m_p_ptCollection[m_iPhysInLast]));
  657. --m_iPhysInLast;
  658. SVSUTIL_ASSERT (m_pFirstBlock->m_p_ptCollection[m_iPhysInLast]);
  659. g_funcFree (m_pFirstBlock->m_p_ptCollection[m_iPhysInLast], g_pvFreeData);
  660. m_pFirstBlock->m_p_ptCollection[m_iPhysInLast] = NULL;
  661. }
  662. return TRUE;
  663. }
  664. //
  665. // Long bitfields
  666. //
  667. class SVSBitField : public SVSAllocClass {
  668. protected:
  669. int m_iLength;
  670. int m_iWLength;
  671. unsigned int *m_puiData;
  672. unsigned int m_uiLastWMask;
  673. public:
  674. SVSBitField (int a_iLength) {
  675. SVSUTIL_ASSERT(a_iLength > 0);
  676. m_iLength = a_iLength;
  677. m_iWLength = (m_iLength / (8 * sizeof(int))) + 1;
  678. m_uiLastWMask = ~((-1) << (m_iLength - (m_iWLength - 1) * 8 * sizeof(int)));
  679. m_puiData = (unsigned int *)g_funcAlloc (m_iWLength * sizeof(int), g_pvAllocData);
  680. }
  681. ~SVSBitField (void) {
  682. g_funcFree (m_puiData, g_pvFreeData);
  683. }
  684. SVSBitField &operator=(int iBit) {
  685. if ((iBit & 1) == 0)
  686. memset (m_puiData, 0, m_iWLength * sizeof(int));
  687. else
  688. memset (m_puiData, 0xff, m_iWLength * sizeof(int));
  689. return *this;
  690. }
  691. SVSBitField &operator=(SVSBitField &bf) {
  692. SVSUTIL_ASSERT (bf.m_iLength == m_iLength);
  693. memcpy (m_puiData, bf.m_puiData, m_iWLength * sizeof(int));
  694. return *this;
  695. }
  696. SVSBitField &operator|=(SVSBitField &bf) {
  697. SVSUTIL_ASSERT (bf.m_iLength == m_iLength);
  698. for (int i = 0 ; i < m_iWLength ; ++i)
  699. m_puiData[i] |= bf.m_puiData[i];
  700. return *this;
  701. }
  702. SVSBitField &operator&=(SVSBitField &bf) {
  703. SVSUTIL_ASSERT (bf.m_iLength == m_iLength);
  704. for (int i = 0 ; i < m_iWLength ; ++i)
  705. m_puiData[i] &= bf.m_puiData[i];
  706. return *this;
  707. }
  708. void Set (int iBitNum) {
  709. SVSUTIL_ASSERT (iBitNum < m_iLength);
  710. int iWord = iBitNum / (sizeof(int) * 8);
  711. unsigned int uiMask = 1 << (iBitNum - iWord * sizeof(int) * 8);
  712. m_puiData[iWord] |= uiMask;
  713. }
  714. void Clear (int iBitNum) {
  715. SVSUTIL_ASSERT (iBitNum < m_iLength);
  716. int iWord = iBitNum / (sizeof(int) * 8);
  717. unsigned int uiMask = 1 << (iBitNum - iWord * sizeof(int) * 8);
  718. m_puiData[iWord] &= ~uiMask;
  719. }
  720. void Inv (int iBitNum) {
  721. SVSUTIL_ASSERT (iBitNum < m_iLength);
  722. int iWord = iBitNum / (sizeof(int) * 8);
  723. unsigned int uiMask = 1 << (iBitNum - iWord * sizeof(int) * 8);
  724. m_puiData[iWord] ^= uiMask;
  725. }
  726. int Get(int iBitNum) {
  727. SVSUTIL_ASSERT (iBitNum < m_iLength);
  728. int iWord = iBitNum / (sizeof(int) * 8);
  729. return (m_puiData[iWord] >> (iBitNum - iWord * sizeof(int) * 8)) & 1;
  730. }
  731. int operator==(int iBit) {
  732. unsigned int iCmp = ((iBit & 1) == 0) ? 0 : (unsigned int)-1;
  733. for (int i = 0 ; i < m_iWLength - 1 ; ++i) {
  734. if (m_puiData[i] != iCmp)
  735. return FALSE;
  736. }
  737. return ((m_puiData[i] ^ iCmp) & m_uiLastWMask) == 0;
  738. }
  739. int operator!=(int iBit) {
  740. return ! (*this == iBit);
  741. }
  742. int operator==(SVSBitField &bf) {
  743. if (bf.m_iLength != m_iLength)
  744. return FALSE;
  745. for (int i = 0 ; i < m_iWLength - 1 ; ++i) {
  746. if (m_puiData[i] != bf.m_puiData[i])
  747. return FALSE;
  748. }
  749. return ((m_puiData[i] ^ bf.m_puiData[i]) & m_uiLastWMask) == 0;
  750. }
  751. int operator!=(SVSBitField &bf) {
  752. return ! (*this == bf);
  753. }
  754. };
  755. //
  756. // Heaps
  757. //
  758. struct SVSHeapEntry {
  759. SVSCKey cKey;
  760. void *pvData;
  761. };
  762. class SVSHeap : public SVSAllocClass, public SVSEnumClass {
  763. protected:
  764. int heap_size;
  765. SVSExpArray<SVSHeapEntry> *pArray;
  766. static int Parent(int i) { return (i - 1) / 2; }
  767. static int Left (int i) { return 2 * i + 1; }
  768. static int Right (int i) { return 2 * (i + 1); }
  769. void Heapify (int i) {
  770. int l = Left(i);
  771. int r = Right(i);
  772. int largest = ((l < heap_size) && ((*pArray)[l].cKey > (*pArray)[i].cKey)) ? l : i;
  773. if ((r < heap_size) && ((*pArray)[r].cKey > (*pArray)[largest].cKey))
  774. largest = r;
  775. if (largest != i) {
  776. SVSHeapEntry he = (*pArray)[i];
  777. (*pArray)[i] = (*pArray)[largest];
  778. (*pArray)[largest] = he;
  779. Heapify (largest);
  780. }
  781. }
  782. public:
  783. SVSHeap (void) {
  784. heap_size = 0;
  785. pArray = new SVSExpArray<SVSHeapEntry>;
  786. }
  787. ~SVSHeap (void) {
  788. delete pArray;
  789. }
  790. int Insert(SVSCKey cKey, void *pvData) {
  791. if (! (*pArray).SRealloc(heap_size + 1))
  792. return FALSE;
  793. int i = heap_size++;
  794. while ((i > 0) && ((*pArray)[Parent(i)].cKey < cKey)) {
  795. (*pArray)[i] = (*pArray)[Parent(i)];
  796. i = Parent(i);
  797. }
  798. (*pArray)[i].cKey = cKey;
  799. (*pArray)[i].pvData = pvData;
  800. return TRUE;
  801. }
  802. void *Remove(SVSHandle hIndex)
  803. {
  804. if (heap_size < 1 || (int) hIndex > heap_size) {
  805. SVSUTIL_ASSERT(0);
  806. return NULL;
  807. }
  808. hIndex = hIndex - 1;
  809. void *pvResult = (*pArray)[hIndex].pvData;
  810. --heap_size;
  811. (*pArray)[hIndex] = (*pArray)[heap_size];
  812. Heapify(hIndex);
  813. return pvResult;
  814. }
  815. int IsEmpty (void) {
  816. return heap_size < 1;
  817. }
  818. void *Peek (SVSCKey *pcKey) {
  819. if (heap_size < 1) {
  820. SVSUTIL_ASSERT(0);
  821. return NULL;
  822. }
  823. if (pcKey)
  824. *pcKey = (*pArray)[0].cKey;
  825. return (*pArray)[0].pvData;
  826. }
  827. void *ExtractMax (SVSCKey *pcKey) {
  828. if (heap_size < 1) {
  829. SVSUTIL_ASSERT(0);
  830. return NULL;
  831. }
  832. void *pvResult = (*pArray)[0].pvData;
  833. if (pcKey)
  834. *pcKey = (*pArray)[0].cKey;
  835. --heap_size;
  836. (*pArray)[0] = (*pArray)[heap_size];
  837. Heapify (0);
  838. return pvResult;
  839. }
  840. void Compact (void) {
  841. (*pArray).CRealloc (heap_size);
  842. }
  843. virtual SVSHandle EnumStart (void) {
  844. return heap_size < 1 ? SVSUTIL_HANDLE_INVALID : 1;
  845. }
  846. virtual SVSHandle EnumNext (SVSHandle hEnum) {
  847. return (int)hEnum < heap_size ? hEnum + 1 : SVSUTIL_HANDLE_INVALID;
  848. }
  849. virtual void *EnumGetData (SVSHandle hEnum) {
  850. SVSUTIL_ASSERT ((hEnum > 0) && ((int)hEnum <= heap_size));
  851. return (*pArray)[hEnum - 1].pvData;
  852. }
  853. virtual SVSCKey EnumGetKey (SVSHandle hEnum) {
  854. SVSUTIL_ASSERT ((hEnum > 0) && ((int)hEnum <= heap_size));
  855. return (*pArray)[hEnum - 1].cKey;
  856. }
  857. };
  858. //
  859. // Heap template
  860. //
  861. template <class T> struct SVSTHeapEntry {
  862. T cKey;
  863. void *pvData;
  864. };
  865. template <class T> class SVSTHeap {
  866. protected:
  867. int heap_size;
  868. typedef SVSTHeapEntry<T> X;
  869. SVSExpArray<X> *pArray;
  870. static int Parent(int i) { return (i - 1) / 2; }
  871. static int Left (int i) { return 2 * i + 1; }
  872. static int Right (int i) { return 2 * (i + 1); }
  873. void Heapify (int i) {
  874. int l = Left(i);
  875. int r = Right(i);
  876. int largest = ((l < heap_size) && ((*pArray)[l].cKey > (*pArray)[i].cKey)) ? l : i;
  877. if ((r < heap_size) && ((*pArray)[r].cKey > (*pArray)[largest].cKey))
  878. largest = r;
  879. if (largest != i) {
  880. SVSTHeapEntry<T> he = (*pArray)[i];
  881. (*pArray)[i] = (*pArray)[largest];
  882. (*pArray)[largest] = he;
  883. Heapify (largest);
  884. }
  885. }
  886. public:
  887. SVSTHeap (void) {
  888. heap_size = 0;
  889. pArray = new SVSExpArray < SVSTHeapEntry<T> >;
  890. }
  891. ~SVSTHeap (void) {
  892. delete pArray;
  893. }
  894. int Insert(T cKey, void *pvData) {
  895. if (! (*pArray).SRealloc(heap_size + 1))
  896. return FALSE;
  897. int i = heap_size++;
  898. while ((i > 0) && ((*pArray)[Parent(i)].cKey < cKey)) {
  899. (*pArray)[i] = (*pArray)[Parent(i)];
  900. i = Parent(i);
  901. }
  902. (*pArray)[i].cKey = cKey;
  903. (*pArray)[i].pvData = pvData;
  904. return TRUE;
  905. }
  906. void *Remove(SVSHandle hIndex)
  907. {
  908. if (heap_size < 1 || (int) hIndex > heap_size) {
  909. SVSUTIL_ASSERT(0);
  910. return NULL;
  911. }
  912. hIndex = hIndex - 1;
  913. void *pvResult = (*pArray)[hIndex].pvData;
  914. --heap_size;
  915. (*pArray)[hIndex] = (*pArray)[heap_size];
  916. Heapify(hIndex);
  917. return pvResult;
  918. }
  919. int IsEmpty (void) {
  920. return heap_size < 1;
  921. }
  922. void *Peek (T *pcKey) {
  923. if (heap_size < 1) {
  924. SVSUTIL_ASSERT(0);
  925. return NULL;
  926. }
  927. if (pcKey)
  928. *pcKey = (*pArray)[0].cKey;
  929. return (*pArray)[0].pvData;
  930. }
  931. void *ExtractMax (T *pcKey) {
  932. if (heap_size < 1) {
  933. SVSUTIL_ASSERT(0);
  934. return NULL;
  935. }
  936. void *pvResult = (*pArray)[0].pvData;
  937. if (pcKey)
  938. *pcKey = (*pArray)[0].cKey;
  939. --heap_size;
  940. (*pArray)[0] = (*pArray)[heap_size];
  941. Heapify (0);
  942. return pvResult;
  943. }
  944. void Compact (void) {
  945. (*pArray).CRealloc (heap_size);
  946. }
  947. virtual SVSHandle EnumStart (void) {
  948. return heap_size < 1 ? SVSUTIL_HANDLE_INVALID : 1;
  949. }
  950. virtual SVSHandle EnumNext (SVSHandle hEnum) {
  951. return (int)hEnum < heap_size ? hEnum + 1 : SVSUTIL_HANDLE_INVALID;
  952. }
  953. virtual void *EnumGetData (SVSHandle hEnum) {
  954. SVSUTIL_ASSERT ((hEnum > 0) && ((int)hEnum <= heap_size));
  955. return (*pArray)[hEnum - 1].pvData;
  956. }
  957. virtual T EnumGetKey (SVSHandle hEnum) {
  958. SVSUTIL_ASSERT ((hEnum > 0) && ((int)hEnum <= heap_size));
  959. return (*pArray)[hEnum - 1].cKey;
  960. }
  961. };
  962. //
  963. // Handle system
  964. //
  965. #define SVSUTIL_HANDLE_NUMBITS 16
  966. #define SVSUTIL_HANDLE_TAGBITS (sizeof(SVSHandle) * 8 - SVSUTIL_HANDLE_NUMBITS)
  967. #define SVSUTIL_HANDLE_MAXNUM ((1 << SVSUTIL_HANDLE_NUMBITS) - 1)
  968. #define SVSUTIL_HANDLE_MAXTAG ((1 << SVSUTIL_HANDLE_TAGBITS) - 1)
  969. #define SVSUTIL_HANDLE_TOTAG(h) ((h) >> SVSUTIL_HANDLE_NUMBITS)
  970. #define SVSUTIL_HANDLE_TONUM(h) ((h) & SVSUTIL_HANDLE_MAXNUM)
  971. class SVSPrivateHandle : public SVSAllocClass {
  972. protected:
  973. union {
  974. void *pvData;
  975. int iNextFree;
  976. };
  977. struct {
  978. int iTag : 24;
  979. unsigned int fFree : 1;
  980. };
  981. friend class SVSHandleSystem;
  982. friend class SVSSimpleHandleSystem;
  983. };
  984. class SVSHandleSystem : public SVSAllocClass {
  985. protected:
  986. SVSExpArray<SVSPrivateHandle> *pArray;
  987. int iFreeNdx;
  988. int iArraySize;
  989. public:
  990. SVSHandle AllocHandle (void *a_pvData) {
  991. SVSUTIL_ASSERT (a_pvData != NULL);
  992. SVSUTIL_ASSERT (iFreeNdx < iArraySize);
  993. SVSUTIL_ASSERT (iArraySize >= 0);
  994. if (iFreeNdx == -1) {
  995. if (iArraySize >= SVSUTIL_HANDLE_MAXNUM)
  996. return FALSE;
  997. if (! (*pArray).SRealloc (iArraySize + 1))
  998. return SVSUTIL_HANDLE_INVALID;
  999. iFreeNdx = iArraySize;
  1000. (*pArray)[iArraySize].iNextFree = -1;
  1001. (*pArray)[iArraySize].iTag = 1;
  1002. (*pArray)[iArraySize].fFree = TRUE;
  1003. ++iArraySize;
  1004. }
  1005. SVSUTIL_ASSERT ((iFreeNdx >= 0) && (iFreeNdx < iArraySize));
  1006. SVSPrivateHandle *psHandle = &(*pArray)[iFreeNdx];
  1007. int iNdx = iFreeNdx;
  1008. SVSUTIL_ASSERT (psHandle->fFree);
  1009. iFreeNdx = psHandle->iNextFree;
  1010. psHandle->pvData = a_pvData;
  1011. psHandle->fFree = FALSE;
  1012. psHandle->iTag += 1;
  1013. if (psHandle->iTag >= SVSUTIL_HANDLE_MAXTAG)
  1014. psHandle->iTag = 1;
  1015. return (psHandle->iTag << SVSUTIL_HANDLE_NUMBITS) | iNdx;
  1016. }
  1017. void *CloseHandle (SVSHandle h) {
  1018. SVSUTIL_ASSERT (iFreeNdx < iArraySize);
  1019. int iTag = SVSUTIL_HANDLE_TOTAG(h);
  1020. int iNum = SVSUTIL_HANDLE_TONUM(h);
  1021. if ((iNum >= iArraySize) || (iTag != (*pArray)[iNum].iTag))
  1022. return NULL;
  1023. SVSUTIL_ASSERT (iArraySize > 0);
  1024. SVSPrivateHandle *psHandle = &(*pArray)[iNum];
  1025. void *pvData = psHandle->pvData;
  1026. SVSUTIL_ASSERT (! psHandle->fFree);
  1027. psHandle->iNextFree = iFreeNdx;
  1028. psHandle->fFree = TRUE;
  1029. iFreeNdx = iNum;
  1030. if (++psHandle->iTag >= SVSUTIL_HANDLE_MAXTAG)
  1031. psHandle->iTag = 1;
  1032. return pvData;
  1033. }
  1034. void *TranslateHandle (SVSHandle h) {
  1035. SVSUTIL_ASSERT (iFreeNdx < iArraySize);
  1036. int iTag = SVSUTIL_HANDLE_TOTAG(h);
  1037. int iNum = SVSUTIL_HANDLE_TONUM(h);
  1038. if ((iNum >= iArraySize) || (iTag != (*pArray)[iNum].iTag))
  1039. return NULL;
  1040. SVSUTIL_ASSERT (iArraySize > 0);
  1041. SVSUTIL_ASSERT (! (*pArray)[iNum].fFree);
  1042. return (*pArray)[iNum].pvData;
  1043. }
  1044. void *ReAssociate (SVSHandle h, void *pvData2) {
  1045. SVSUTIL_ASSERT (iFreeNdx < iArraySize);
  1046. SVSUTIL_ASSERT (pvData2 != NULL);
  1047. int iTag = SVSUTIL_HANDLE_TOTAG(h);
  1048. int iNum = SVSUTIL_HANDLE_TONUM(h);
  1049. if ((iNum >= iArraySize) || (iTag != (*pArray)[iNum].iTag))
  1050. return NULL;
  1051. SVSUTIL_ASSERT (iArraySize > 0);
  1052. SVSUTIL_ASSERT (! (*pArray)[iNum].fFree);
  1053. void *pvResult = (*pArray)[iNum].pvData;
  1054. (*pArray)[iNum].pvData = pvData2;
  1055. return pvResult;
  1056. }
  1057. int FilterHandles (int (*pFuncFilter)(SVSHandle, void *), void *pvArg) {
  1058. unsigned int iProcessed = 0;
  1059. for (int i = 0 ; i < iArraySize ; ++i) {
  1060. if (! (*pArray)[i].fFree)
  1061. iProcessed += pFuncFilter (((*pArray)[i].iTag << SVSUTIL_HANDLE_NUMBITS) | i,
  1062. pvArg);
  1063. }
  1064. return iProcessed;
  1065. }
  1066. SVSHandleSystem (void) {
  1067. pArray = new SVSExpArray<SVSPrivateHandle>;
  1068. iFreeNdx = -1;
  1069. iArraySize = 0;
  1070. }
  1071. ~SVSHandleSystem (void) {
  1072. delete pArray;
  1073. }
  1074. };
  1075. class SVSSimpleHandleSystem : public SVSAllocClass {
  1076. protected:
  1077. SVSPrivateHandle *pArray;
  1078. int iFreeNdx;
  1079. int iArraySize;
  1080. int iMaxArraySize;
  1081. public:
  1082. SVSHandle AllocHandle (void *a_pvData) {
  1083. SVSUTIL_ASSERT (a_pvData != NULL);
  1084. SVSUTIL_ASSERT (iFreeNdx < iArraySize);
  1085. SVSUTIL_ASSERT (iArraySize >= 0);
  1086. if (iFreeNdx == -1) {
  1087. if (iArraySize >= iMaxArraySize)
  1088. return FALSE;
  1089. iFreeNdx = iArraySize;
  1090. pArray[iArraySize].iNextFree = -1;
  1091. pArray[iArraySize].iTag = 1;
  1092. pArray[iArraySize].fFree = TRUE;
  1093. ++iArraySize;
  1094. }
  1095. SVSUTIL_ASSERT ((iFreeNdx >= 0) && (iFreeNdx < iArraySize));
  1096. SVSPrivateHandle *psHandle = &pArray[iFreeNdx];
  1097. int iNdx = iFreeNdx;
  1098. SVSUTIL_ASSERT (psHandle->fFree);
  1099. iFreeNdx = psHandle->iNextFree;
  1100. psHandle->pvData = a_pvData;
  1101. psHandle->fFree = FALSE;
  1102. psHandle->iTag += 1;
  1103. if (psHandle->iTag >= SVSUTIL_HANDLE_MAXTAG)
  1104. psHandle->iTag = 1;
  1105. return (psHandle->iTag << SVSUTIL_HANDLE_NUMBITS) | iNdx;
  1106. }
  1107. void *CloseHandle (SVSHandle h) {
  1108. SVSUTIL_ASSERT (iFreeNdx < iArraySize);
  1109. int iTag = SVSUTIL_HANDLE_TOTAG(h);
  1110. int iNum = SVSUTIL_HANDLE_TONUM(h);
  1111. if ((iNum >= iArraySize) || (iTag != pArray[iNum].iTag))
  1112. return NULL;
  1113. SVSUTIL_ASSERT (iArraySize > 0);
  1114. SVSPrivateHandle *psHandle = &pArray[iNum];
  1115. void *pvData = psHandle->pvData;
  1116. SVSUTIL_ASSERT (! psHandle->fFree);
  1117. psHandle->iNextFree = iFreeNdx;
  1118. psHandle->fFree = TRUE;
  1119. iFreeNdx = iNum;
  1120. if (++psHandle->iTag >= SVSUTIL_HANDLE_MAXTAG)
  1121. psHandle->iTag = 1;
  1122. return pvData;
  1123. }
  1124. void *TranslateHandle (SVSHandle h) {
  1125. SVSUTIL_ASSERT (iFreeNdx < iArraySize);
  1126. int iTag = SVSUTIL_HANDLE_TOTAG(h);
  1127. int iNum = SVSUTIL_HANDLE_TONUM(h);
  1128. if ((iNum >= iArraySize) || (iTag != pArray[iNum].iTag))
  1129. return NULL;
  1130. SVSUTIL_ASSERT (iArraySize > 0);
  1131. SVSUTIL_ASSERT (! pArray[iNum].fFree);
  1132. return pArray[iNum].pvData;
  1133. }
  1134. void *ReAssociate (SVSHandle h, void *pvData2) {
  1135. SVSUTIL_ASSERT (iFreeNdx < iArraySize);
  1136. SVSUTIL_ASSERT (pvData2 != NULL);
  1137. int iTag = SVSUTIL_HANDLE_TOTAG(h);
  1138. int iNum = SVSUTIL_HANDLE_TONUM(h);
  1139. if ((iNum >= iArraySize) || (iTag != pArray[iNum].iTag))
  1140. return NULL;
  1141. SVSUTIL_ASSERT (iArraySize > 0);
  1142. SVSUTIL_ASSERT (! pArray[iNum].fFree);
  1143. void *pvResult = pArray[iNum].pvData;
  1144. pArray[iNum].pvData = pvData2;
  1145. return pvResult;
  1146. }
  1147. int FilterHandles (int (*pFuncFilter)(SVSHandle, void *), void *pvArg) {
  1148. unsigned int iProcessed = 0;
  1149. for (int i = 0 ; i < iArraySize ; ++i) {
  1150. if (! pArray[i].fFree)
  1151. iProcessed += pFuncFilter ((pArray[i].iTag << SVSUTIL_HANDLE_NUMBITS) | i,
  1152. pvArg);
  1153. }
  1154. return iProcessed;
  1155. }
  1156. SVSSimpleHandleSystem (int a_iMaxArraySize) {
  1157. pArray = (SVSPrivateHandle *)g_funcAlloc (sizeof(SVSPrivateHandle) * a_iMaxArraySize, g_pvAllocData);
  1158. iFreeNdx = -1;
  1159. iArraySize = 0;
  1160. iMaxArraySize = a_iMaxArraySize;
  1161. }
  1162. ~SVSSimpleHandleSystem (void) {
  1163. g_funcFree (pArray, g_pvFreeData);
  1164. }
  1165. };
  1166. #define SVSUTIL_PGUID_ELEMENTS(p) \
  1167. p->Data1, p->Data2, p->Data3,\
  1168. p->Data4[0], p->Data4[1], p->Data4[2], p->Data4[3],\
  1169. p->Data4[4], p->Data4[5], p->Data4[6], p->Data4[7]
  1170. #define SVSUTIL_RGUID_ELEMENTS(p) \
  1171. p.Data1, p.Data2, p.Data3,\
  1172. p.Data4[0], p.Data4[1], p.Data4[2], p.Data4[3],\
  1173. p.Data4[4], p.Data4[5], p.Data4[6], p.Data4[7]
  1174. #define SVSUTIL_GUID_FORMAT L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"
  1175. #define SVSUTIL_GUID_STR_LENGTH (8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12)
  1176. //
  1177. // C-like interface
  1178. //
  1179. extern "C" {
  1180. SVSQueue *svsutil_GetQueue (unsigned int uiChunkSize);
  1181. int svsutil_IsQueueEmpty (SVSQueue *pQueue);
  1182. int svsutil_PutInQueue (SVSQueue *pQueue, void *pvDatum);
  1183. void *svsutil_GetFromQueue (SVSQueue *pQueue);
  1184. void *svsutil_PeekQueue (SVSQueue *pQueue);
  1185. void svsutil_CompactQueue (SVSQueue *pQueue);
  1186. void svsutil_DestroyQueue (SVSQueue *pQueue);
  1187. SVSStack *svsutil_GetStack (unsigned int uiChunkSize);
  1188. int svsutil_IsStackEmpty (SVSStack *pStack);
  1189. int svsutil_PushStack (SVSStack *pStack, void *pvDatum);
  1190. void *svsutil_PopStack (SVSStack *pStack);
  1191. void *svsutil_PeekStack (SVSStack *pStack);
  1192. void svsutil_CompactStack (SVSStack *pStack);
  1193. void svsutil_DestroyStack (SVSStack *pStack);
  1194. SVSStack *svsutil_GetHeap (void);
  1195. int svsutil_IsHeapEmpty (SVSHeap *pHeap);
  1196. int svsutil_InsertInHeap (SVSHeap *pHeap, SVSCKey *pcKey, void *pvDatum);
  1197. void *svsutil_ExtractMaxFromHeap (SVSHeap *pHeap, SVSCKey *pcKey);
  1198. void *svsutil_PeekHeap (SVSHeap *pHeap, SVSCKey *pcKet);
  1199. void svsutil_CompactHeap (SVSHeap *pHeap);
  1200. void svsutil_DestroyHeap (SVSHeap *pHeap);
  1201. }
  1202. //
  1203. // Thread pool
  1204. //
  1205. // For converting between filetime and tick measurements
  1206. #define SVS_FILETIME_TO_MILLISECONDS ((__int64)10000L)
  1207. #if defined (UNDER_CE) && !defined (InterlockedCompareExchange)
  1208. #define InterlockedCompareExchange(ptr, newval, oldval) \
  1209. ((PVOID)InterlockedTestExchange((LPLONG)ptr, (LONG)oldval, (LONG)newval))
  1210. #endif
  1211. typedef unsigned long SVSCookie;
  1212. #define SVS_DEBUG_THREAD_WORKER 0
  1213. #define SVS_DEBUG_THREAD_SCHEDULE_EVENT 0
  1214. #define SVS_DEBUG_THREAD_QUEUE 0
  1215. #define SVS_THREAD_POOL_DEFAULT_MAX_THREADS 20
  1216. class SVSThreadBlock
  1217. {
  1218. friend class SVSThreadPool;
  1219. protected:
  1220. LPTHREAD_START_ROUTINE m_pfnThread;
  1221. LPVOID m_lpParameter;
  1222. SVSCookie m_ulCookie;
  1223. unsigned long Run() {
  1224. SVSUTIL_ASSERT (m_pfnThread && m_ulCookie);
  1225. return (m_pfnThread)(m_lpParameter);
  1226. }
  1227. };
  1228. inline __int64 SVSGetCurrentFT(void)
  1229. {
  1230. SYSTEMTIME st;
  1231. __int64 ft;
  1232. GetSystemTime(&st);
  1233. SystemTimeToFileTime(&st,(LPFILETIME) &ft);
  1234. return ft;
  1235. }
  1236. // User application uses this in GetStatistics
  1237. typedef struct
  1238. {
  1239. LONG fRunning;
  1240. unsigned long cThreadsRunning;
  1241. unsigned long cThreadsIdle;
  1242. unsigned long ulAverageDelayTime;
  1243. long cJobsExecuted;
  1244. } SVS_THREAD_POOL_STATS;
  1245. //
  1246. // Used internally by SVSThreadPool for statistics
  1247. //
  1248. #define SVS_THREAD_STATS_RESIZE 5
  1249. class CSVSThreadPoolInternalStats
  1250. {
  1251. double m_dAvgArray[2];
  1252. __int64 m_ftPrev;
  1253. int m_iSlot;
  1254. int m_iIndex;
  1255. long m_cJobsExecuted;
  1256. public:
  1257. CSVSThreadPoolInternalStats() {
  1258. memset(this,0,sizeof(*this));
  1259. }
  1260. // Called with Lock held by caller.
  1261. void UpdateStatistics(void) {
  1262. __int64 ftNow = SVSGetCurrentFT();
  1263. __int64 ftDelta;
  1264. m_cJobsExecuted++;
  1265. ftDelta = m_ftPrev ? ftNow - m_ftPrev : 0;
  1266. m_ftPrev = ftNow;
  1267. m_dAvgArray[m_iSlot] += ftDelta;
  1268. m_iIndex++;
  1269. if (m_iIndex == SVS_THREAD_STATS_RESIZE)
  1270. {
  1271. m_dAvgArray[m_iSlot] /= SVS_THREAD_STATS_RESIZE;
  1272. m_iSlot = (m_iSlot + 1) % 2;
  1273. m_dAvgArray[m_iSlot] = 0;
  1274. m_iIndex = 0;
  1275. }
  1276. }
  1277. // Called with Lock held by caller.
  1278. double CalculateAverageDelay(void) {
  1279. double dRet;
  1280. if (m_cJobsExecuted == 0)
  1281. {
  1282. dRet = 0;
  1283. }
  1284. else if (m_cJobsExecuted < SVS_THREAD_STATS_RESIZE)
  1285. {
  1286. dRet = m_dAvgArray[0] / m_cJobsExecuted;
  1287. }
  1288. else
  1289. {
  1290. dRet = (m_dAvgArray[!m_iSlot]*SVS_THREAD_STATS_RESIZE +
  1291. m_dAvgArray[m_iSlot]) / (m_iIndex + SVS_THREAD_STATS_RESIZE);
  1292. }
  1293. return (double) (dRet / SVS_FILETIME_TO_MILLISECONDS);
  1294. }
  1295. int NumberOfJobsExecuted(void) {
  1296. return m_cJobsExecuted;
  1297. }
  1298. };
  1299. class SVSThreadPool : public SVSSynch, public SVSAllocClass, public SVSTHeap<__int64>
  1300. {
  1301. protected:
  1302. FixedMemDescr *m_pNodeMem; // physical memory of SVSThreadBlock structures, both ones in use and not.
  1303. HANDLE m_hWorkerEvent; // signals running worker threads we're ready
  1304. HANDLE m_hTimerEvent; // signals running worker threads we're ready
  1305. long m_fRunning; // Are we accepting new thread requests?
  1306. unsigned long m_cMaxThreadsAllowed; // Maximum # of threads to allow
  1307. unsigned long m_cThreadsRunning; // # of threads executing user code
  1308. unsigned long m_cThreadsIdle; // # of threads not executing user code but available.
  1309. SVSCookie m_ulCookie; // Value of next cookie to assign
  1310. long m_fTimerLock; // Used to sync which worker is the timer
  1311. #if defined (SVSUTIL_DEBUG_THREADS)
  1312. CSVSThreadPoolInternalStats m_Stats; // Perf statistics.
  1313. #endif
  1314. BOOL GetTimer(void) {
  1315. return !InterlockedCompareExchange(&m_fTimerLock,1,0);
  1316. }
  1317. void ReleaseTimer(void) {
  1318. m_fTimerLock = 0;
  1319. }
  1320. // BUGBUG -- what happens if someone changes system time??
  1321. // Called with Lock held by caller.
  1322. SVSThreadBlock * GetNextJobFromQueue()
  1323. {
  1324. SVSUTIL_ASSERT(IsLocked());
  1325. __int64 ftNow;
  1326. __int64 ftNextEvent;
  1327. SVSThreadBlock *ret;
  1328. if (IsEmpty() || !m_fRunning)
  1329. return NULL;
  1330. ret = (SVSThreadBlock *) Peek(&ftNextEvent);
  1331. ftNow = SVSGetCurrentFT();
  1332. if (ftNow >= ~ftNextEvent)
  1333. {
  1334. ExtractMax(NULL);
  1335. }
  1336. else
  1337. {
  1338. ret = NULL;
  1339. }
  1340. return ret;
  1341. }
  1342. // Called with Lock held by caller.
  1343. SVSCookie PutOnWorkerQueue(LPTHREAD_START_ROUTINE pfn, LPVOID lpParameter,__int64 ftExecuteTime)
  1344. {
  1345. SVSUTIL_ASSERT(IsLocked());
  1346. SVSThreadBlock *pThreadBlock = (SVSThreadBlock *)svsutil_GetFixed (m_pNodeMem);
  1347. pThreadBlock->m_pfnThread = pfn;
  1348. pThreadBlock->m_lpParameter = lpParameter;
  1349. pThreadBlock->m_ulCookie = ++m_ulCookie;
  1350. if (! Insert(~ftExecuteTime,pThreadBlock))
  1351. return 0;
  1352. if (m_cThreadsRunning == 0 && m_cThreadsIdle == 0)
  1353. {
  1354. HANDLE hThread = CreateThread(0,0,SVSThreadPoolWorkerThread,this,0,0);
  1355. SVSUTIL_ASSERT (hThread);
  1356. if (hThread)
  1357. {
  1358. CloseHandle(hThread);
  1359. m_cThreadsIdle++;
  1360. }
  1361. }
  1362. SetEvent(m_hTimerEvent);
  1363. return pThreadBlock->m_ulCookie;
  1364. }
  1365. // Called with Lock held by caller.
  1366. unsigned long GetDelayUntilNextEvent()
  1367. {
  1368. SVSUTIL_ASSERT(IsLocked());
  1369. __int64 ftNow;
  1370. __int64 ftNextEvent;
  1371. if (IsEmpty())
  1372. return INFINITE;
  1373. Peek(&ftNextEvent);
  1374. ftNextEvent = ~ftNextEvent;
  1375. ftNow = SVSGetCurrentFT();
  1376. // if event has passed, set to 0 timeout.
  1377. if (ftNow >= ftNextEvent)
  1378. return 0;
  1379. return (unsigned long) ((ftNextEvent - ftNow) / SVS_FILETIME_TO_MILLISECONDS);
  1380. }
  1381. void Worker()
  1382. {
  1383. SVSThreadBlock *pThreadBlock = NULL;
  1384. BOOL fTimer;
  1385. unsigned long ulTimeOut;
  1386. HANDLE hEvent;
  1387. while (m_fRunning)
  1388. {
  1389. fTimer = GetTimer();
  1390. if (fTimer)
  1391. {
  1392. hEvent = m_hTimerEvent;
  1393. Lock();
  1394. ulTimeOut = GetDelayUntilNextEvent();
  1395. Unlock();
  1396. }
  1397. else
  1398. {
  1399. ulTimeOut = 5*60000;
  1400. hEvent = m_hWorkerEvent;
  1401. }
  1402. if (WAIT_TIMEOUT == WaitForSingleObject(hEvent,ulTimeOut))
  1403. {
  1404. // If we're not the timer thread then we're done executing...
  1405. if (!fTimer)
  1406. {
  1407. break;
  1408. }
  1409. }
  1410. else if (!fTimer)
  1411. {
  1412. // We get the worker thread event if a timer has been freed
  1413. // or if we're shutting down, in either case we want
  1414. // to go to top of while loop.
  1415. continue;
  1416. }
  1417. SVSUTIL_ASSERT(fTimer);
  1418. ReleaseTimer();
  1419. Lock();
  1420. pThreadBlock = GetNextJobFromQueue();
  1421. if (!pThreadBlock)
  1422. {
  1423. Unlock();
  1424. continue;
  1425. }
  1426. m_cThreadsIdle--;
  1427. m_cThreadsRunning++;
  1428. if (m_cThreadsIdle)
  1429. {
  1430. SetEvent(m_hWorkerEvent);
  1431. }
  1432. else if (m_cThreadsRunning < m_cMaxThreadsAllowed)
  1433. {
  1434. HANDLE hThread = CreateThread(0,0,SVSThreadPoolWorkerThread,this,0,0);
  1435. SVSUTIL_ASSERT (hThread);
  1436. if (hThread)
  1437. {
  1438. CloseHandle(hThread);
  1439. m_cThreadsIdle++;
  1440. }
  1441. }
  1442. #if defined (SVSUTIL_DEBUG_THREADS)
  1443. m_Stats.UpdateStatistics();
  1444. #endif
  1445. Unlock();
  1446. pThreadBlock->Run();
  1447. Lock();
  1448. svsutil_FreeFixed(pThreadBlock,m_pNodeMem);
  1449. m_cThreadsIdle++;
  1450. m_cThreadsRunning--;
  1451. Unlock();
  1452. }
  1453. Lock(); m_cThreadsIdle--; Unlock();
  1454. }
  1455. static unsigned long WINAPI SVSThreadPoolWorkerThread(LPVOID lpv)
  1456. {
  1457. SVSThreadPool *pThreadPool = (SVSThreadPool *) lpv;
  1458. pThreadPool->Worker();
  1459. return 0;
  1460. }
  1461. public:
  1462. SVSThreadPool (unsigned long ulMaxThreads=SVS_THREAD_POOL_DEFAULT_MAX_THREADS)
  1463. {
  1464. m_cMaxThreadsAllowed = ulMaxThreads;
  1465. m_hTimerEvent = m_hWorkerEvent = 0;
  1466. m_cThreadsIdle = m_cThreadsRunning = m_ulCookie = 0;
  1467. m_fTimerLock = FALSE;
  1468. m_pNodeMem = svsutil_AllocFixedMemDescr (sizeof(SVSThreadBlock), 20);
  1469. pArray = new SVSExpArray<X>; // typedef SVSTHeapEntry<__int64> X;
  1470. m_hWorkerEvent = CreateEvent (0, FALSE, FALSE, 0);
  1471. m_hTimerEvent = CreateEvent (0, FALSE, FALSE, 0);
  1472. SVSUTIL_ASSERT ( m_pNodeMem && pArray && m_hWorkerEvent && m_hTimerEvent);
  1473. if (m_pNodeMem && pArray && m_hWorkerEvent && m_hTimerEvent)
  1474. {
  1475. m_fRunning = TRUE;
  1476. }
  1477. }
  1478. ~SVSThreadPool()
  1479. {
  1480. Shutdown();
  1481. SVSUTIL_ASSERT (m_cThreadsRunning == 0 && m_cThreadsIdle == 0);
  1482. if (m_pNodeMem)
  1483. svsutil_ReleaseFixedNonEmpty(m_pNodeMem);
  1484. if (m_hWorkerEvent)
  1485. CloseHandle (m_hWorkerEvent);
  1486. if (m_hTimerEvent)
  1487. CloseHandle (m_hTimerEvent);
  1488. }
  1489. // Shutdown all timers and running threads. Once shutdown has started,
  1490. // no threads or timers may ever fire again
  1491. unsigned long Shutdown()
  1492. {
  1493. m_fRunning = FALSE;
  1494. while (m_cThreadsRunning || m_cThreadsIdle)
  1495. {
  1496. SetEvent(m_hTimerEvent);
  1497. SetEvent(m_hWorkerEvent);
  1498. Sleep(1000);
  1499. }
  1500. return TRUE;
  1501. }
  1502. SVSCookie ScheduleEvent(LPTHREAD_START_ROUTINE pfn, LPVOID lpParameter, unsigned long ulDelayTime=0)
  1503. {
  1504. SVSCookie ret = 0;
  1505. __int64 ftExecuteTime;
  1506. if (!m_fRunning)
  1507. {
  1508. return 0;
  1509. }
  1510. ftExecuteTime = SVSGetCurrentFT();
  1511. ftExecuteTime += ulDelayTime * SVS_FILETIME_TO_MILLISECONDS;
  1512. Lock();
  1513. ret = PutOnWorkerQueue(pfn,lpParameter,ftExecuteTime);
  1514. Unlock();
  1515. return ret;
  1516. }
  1517. SVSCookie StartTimer(LPTHREAD_START_ROUTINE pfn, LPVOID lpParameter,unsigned long ulDelayTime)
  1518. {
  1519. return ScheduleEvent(pfn,lpParameter,ulDelayTime);
  1520. }
  1521. BOOL UnScheduleEvent(SVSCookie ulCookie)
  1522. {
  1523. BOOL ret = FALSE;
  1524. SVSHandle hEnum;
  1525. SVSThreadBlock *pThreadBlock;
  1526. Lock();
  1527. hEnum = EnumStart();
  1528. do
  1529. {
  1530. pThreadBlock = (SVSThreadBlock *)EnumGetData(hEnum);
  1531. if (pThreadBlock->m_ulCookie == ulCookie)
  1532. {
  1533. ret = Remove(hEnum) ? TRUE : FALSE;
  1534. break;
  1535. }
  1536. } while (SVSUTIL_HANDLE_INVALID != (hEnum = EnumNext(hEnum)));
  1537. Unlock();
  1538. return ret;
  1539. }
  1540. BOOL StopTimer(SVSCookie ulCookie)
  1541. {
  1542. return UnScheduleEvent(ulCookie);
  1543. }
  1544. #if defined (SVSUTIL_DEBUG_THREADS)
  1545. public:
  1546. void GetStatistics(SVS_THREAD_POOL_STATS *pThreadStats)
  1547. {
  1548. if (!pThreadStats)
  1549. return;
  1550. Lock();
  1551. pThreadStats->fRunning = m_fRunning;
  1552. pThreadStats->cThreadsRunning = m_cThreadsRunning;
  1553. pThreadStats->cThreadsIdle = m_cThreadsIdle;
  1554. pThreadStats->ulAverageDelayTime = (unsigned long) m_Stats.CalculateAverageDelay();
  1555. pThreadStats->cJobsExecuted = m_Stats.NumberOfJobsExecuted();
  1556. Unlock();
  1557. }
  1558. #endif // SVSUTIL_DEBUG_THREADS
  1559. };
  1560. #else /* __cplusplus */
  1561. struct SVSQueue;
  1562. struct SVSStack;
  1563. struct SVSHeap;
  1564. struct SVSQueue *svsutil_GetQueue (unsigned int uiChunkSize);
  1565. int svsutil_IsQueueEmpty (struct SVSQueue *pQueue);
  1566. int svsutil_PutInQueue (struct SVSQueue *pQueue, void *pvDatum);
  1567. void *svsutil_GetFromQueue (struct SVSQueue *pQueue);
  1568. void *svsutil_PeekQueue (struct SVSQueue *pQueue);
  1569. void svsutil_CompactQueue (struct SVSQueue *pQueue);
  1570. void svsutil_DestroyQueue (struct SVSQueue *pQueue);
  1571. struct SVSStack *svsutil_GetStack (unsigned int uiChunkSize);
  1572. int svsutil_IsStackEmpty (struct SVSStack *pStack);
  1573. int svsutil_PushStack (struct SVSStack *pStack, void *pvDatum);
  1574. void *svsutil_PopStack (struct SVSStack *pStack);
  1575. void *svsutil_PeekStack (struct SVSStack *pStack);
  1576. void svsutil_CompactStack (struct SVSStack *pStack);
  1577. void svsutil_DestroyStack (struct SVSStack *pStack);
  1578. struct SVSStack *svsutil_GetHeap (void);
  1579. int svsutil_IsHeapEmpty (struct SVSHeap *pHeap);
  1580. int svsutil_InsertInHeap (struct SVSHeap *pHeap, SVSCKey *pcKey, void *pvDatum);
  1581. void *svsutil_ExtractMaxFromHeap (struct SVSHeap *pHeap, SVSCKey *pcKey);
  1582. void *svsutil_PeekHeap (struct SVSHeap *pHeap, SVSCKey *pcKet);
  1583. void svsutil_CompactHeap (struct SVSHeap *pHeap);
  1584. void svsutil_DestroyHeap (struct SVSHeap *pHeap);
  1585. #endif
  1586. #endif /* __svsutil_HXX__ */