商丘数字城管 HPServer

RingBuffer.h 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542
  1. /*
  2. * Copyright: JessMA Open Source (ldcsaa@gmail.com)
  3. *
  4. * Version : 2.3.21
  5. * Author : Bruce Liang
  6. * Website : http://www.jessma.org
  7. * Project : https://github.com/ldcsaa
  8. * Blog : http://www.cnblogs.com/ldcsaa
  9. * Wiki : http://www.oschina.net/p/hp-socket
  10. * QQ Group : 75375912, 44636872
  11. *
  12. * Licensed under the Apache License, Version 2.0 (the "License");
  13. * you may not use this file except in compliance with the License.
  14. * You may obtain a copy of the License at
  15. *
  16. * http://www.apache.org/licenses/LICENSE-2.0
  17. *
  18. * Unless required by applicable law or agreed to in writing, software
  19. * distributed under the License is distributed on an "AS IS" BASIS,
  20. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  21. * See the License for the specific language governing permissions and
  22. * limitations under the License.
  23. */
  24. #pragma once
  25. #include "STLHelper.h"
  26. #include "RWLock.h"
  27. #include "CriticalSection.h"
  28. #define CACHE_LINE 64
  29. #define PACK_SIZE_OF(T) (CACHE_LINE - sizeof(T) % CACHE_LINE)
  30. #if !defined (_WIN64)
  31. #pragma pack(push, 4)
  32. #endif
  33. template <class T, class _PutGuard = CCriSec, class _GetGuard = CCriSec> class CRingBuffer
  34. {
  35. public:
  36. static const UINT DEFAULT_EXPECT = 4096;
  37. public:
  38. BOOL Put(T* pElement)
  39. {
  40. ASSERT(pElement != nullptr);
  41. {
  42. CLocalLock<_PutGuard> locallock(m_csPut);
  43. ULONGLONG seqPut = m_seqPut;
  44. WaitForPut(seqPut);
  45. if(!IsValid()) return FALSE;
  46. DoPut(pElement, seqPut);
  47. }
  48. return TRUE;
  49. }
  50. BOOL TryPut(T* pElement)
  51. {
  52. ASSERT(pElement != nullptr);
  53. if(!IsValid() || !HasPutSpace(m_seqPut))
  54. return FALSE;
  55. {
  56. CLocalLock<_PutGuard> locallock(m_csPut);
  57. ULONGLONG seqPut = m_seqPut;
  58. if(!IsValid() || !HasPutSpace(seqPut))
  59. return FALSE;
  60. DoPut(pElement, seqPut);
  61. }
  62. return TRUE;
  63. }
  64. BOOL PutBatch(T* pElements[], int& iCount)
  65. {
  66. ASSERT(pElements != nullptr && iCount > 0);
  67. {
  68. CLocalLock<_PutGuard> locallock(m_csPut);
  69. ULONGLONG seqPut = m_seqPut;
  70. for(int i = 0; i < iCount; ++i)
  71. {
  72. WaitForPut(seqPut);
  73. if(!IsValid())
  74. {
  75. iCount = i;
  76. return FALSE;
  77. }
  78. DoPut(*(pElements + i), seqPut);
  79. }
  80. }
  81. return TRUE;
  82. }
  83. BOOL TryPutBatch(T* pElements[], int& iCount)
  84. {
  85. ASSERT(pElements != nullptr && iCount > 0);
  86. if(!IsValid() || !HasPutSpace(m_seqPut))
  87. {
  88. iCount = 0;
  89. return FALSE;
  90. }
  91. {
  92. CLocalLock<_PutGuard> locallock(m_csPut);
  93. ULONGLONG seqPut = m_seqPut;
  94. for(int i = 0; i < iCount; ++i)
  95. {
  96. if(!IsValid() || !HasPutSpace(seqPut))
  97. {
  98. iCount = i;
  99. return FALSE;
  100. }
  101. DoPut(*(pElements + i), seqPut);
  102. }
  103. }
  104. return TRUE;
  105. }
  106. BOOL Get(T** pElement)
  107. {
  108. ASSERT(pElement != nullptr);
  109. {
  110. CLocalLock<_GetGuard> locallock(m_csGet);
  111. ULONGLONG seqGet = m_seqGet;
  112. WaitForGet(seqGet);
  113. if(!IsValid()) return FALSE;
  114. DoGet(pElement, seqGet);
  115. }
  116. return TRUE;
  117. }
  118. BOOL TryGet(T** pElement)
  119. {
  120. ASSERT(pElement != nullptr);
  121. if(!IsValid() || !HasGetSpace(m_seqGet))
  122. return FALSE;
  123. {
  124. CLocalLock<_GetGuard> locallock(m_csGet);
  125. ULONGLONG seqGet = m_seqGet;
  126. if(!IsValid() || !HasGetSpace(seqGet))
  127. return FALSE;
  128. DoGet(pElement, seqGet);
  129. }
  130. return TRUE;
  131. }
  132. BOOL GetBatch(T* pElements[], int& iCount)
  133. {
  134. ASSERT(pElements != nullptr && iCount > 0);
  135. {
  136. CLocalLock<_GetGuard> locallock(m_csGet);
  137. ULONGLONG seqGet = m_seqGet;
  138. for(int i = 0; i < iCount; ++i)
  139. {
  140. WaitForGet(seqGet);
  141. if(!IsValid())
  142. {
  143. iCount = i;
  144. return FALSE;
  145. }
  146. DoGet(pElements + i, seqGet);
  147. }
  148. }
  149. return TRUE;
  150. }
  151. BOOL TryGetBatch(T* pElements[], int& iCount)
  152. {
  153. ASSERT(pElements != nullptr && iCount > 0);
  154. if(!IsValid() || !HasGetSpace(m_seqGet))
  155. {
  156. iCount = 0;
  157. return FALSE;
  158. }
  159. {
  160. CLocalLock<_GetGuard> locallock(m_csGet);
  161. ULONGLONG seqGet = m_seqGet;
  162. for(int i = 0; i < iCount; ++i)
  163. {
  164. if(!IsValid() || !HasGetSpace(seqGet))
  165. {
  166. iCount = i;
  167. return FALSE;
  168. }
  169. DoGet(pElements + i, seqGet);
  170. }
  171. }
  172. return TRUE;
  173. }
  174. BOOL Peek(T** pElement)
  175. {
  176. ASSERT(pElement != nullptr);
  177. ULONGLONG seqGet = m_seqGet;
  178. if(!IsValid() || !HasGetSpace(seqGet))
  179. return FALSE;
  180. DoPeek(pElement, seqGet);
  181. return TRUE;
  182. }
  183. private:
  184. void DoPut(T* pElement, ULONGLONG& seqPut)
  185. {
  186. DWORD index = seqPut & (m_dwReal - 1);
  187. *(m_pv + index) = pElement;
  188. ++seqPut;
  189. m_seqPut = seqPut;
  190. }
  191. void DoGet(T** pElement, ULONGLONG& seqGet)
  192. {
  193. DWORD index = seqGet & (m_dwReal - 1);
  194. *(pElement) = *(m_pv + index);
  195. ++seqGet;
  196. m_seqGet = seqGet;
  197. }
  198. void DoPeek(T** pElement, ULONGLONG& seqGet)
  199. {
  200. DWORD index = seqGet & (m_dwReal - 1);
  201. *(pElement) = *(m_pv + index);
  202. }
  203. BOOL HasPutSpace(ULONGLONG seqPut)
  204. {
  205. return (seqPut - m_seqGet < m_dwReal);
  206. }
  207. void WaitForPut(ULONGLONG seqPut)
  208. {
  209. for(DWORD w = 0; IsValid(); ++w)
  210. {
  211. if(HasPutSpace(seqPut))
  212. break;
  213. ::YieldThread(w);
  214. }
  215. }
  216. BOOL HasGetSpace(ULONGLONG seqGet)
  217. {
  218. return (m_seqPut - seqGet > 0);
  219. }
  220. void WaitForGet(ULONGLONG seqGet)
  221. {
  222. for(DWORD w = 0; IsValid(); ++w)
  223. {
  224. if(HasGetSpace(seqGet))
  225. break;
  226. ::YieldThread(w);
  227. }
  228. }
  229. DWORD Revise(DWORD dwExpect)
  230. {
  231. int index = 0;
  232. int shift = sizeof(DWORD) * 8 - 1;
  233. for(int i = shift; i >= 0; i--)
  234. {
  235. if(index == 0)
  236. {
  237. if(dwExpect & (1 << i))
  238. {
  239. index = i;
  240. if(index == shift)
  241. break;
  242. }
  243. }
  244. else
  245. {
  246. if(dwExpect & (1 << i))
  247. ++index;
  248. break;
  249. }
  250. }
  251. return 1 << index;
  252. }
  253. public:
  254. CRingBuffer(DWORD uiExpect = DEFAULT_EXPECT)
  255. : m_pv(nullptr)
  256. , m_dwReal(0)
  257. , m_seqPut(0)
  258. , m_seqGet(0)
  259. {
  260. Reset(uiExpect);
  261. }
  262. ~CRingBuffer()
  263. {
  264. Reset(0);
  265. }
  266. void Reset(DWORD uiExpect = DEFAULT_EXPECT)
  267. {
  268. if(IsValid())
  269. Destroy();
  270. if(uiExpect > 0)
  271. Create(uiExpect);
  272. }
  273. BOOL IsValid() {return m_pv != nullptr;}
  274. private:
  275. void Create(DWORD dwExpect = DEFAULT_EXPECT)
  276. {
  277. ASSERT(!IsValid() && dwExpect > 0);
  278. m_seqPut = 0;
  279. m_seqGet = 0;
  280. m_dwReal = Revise(dwExpect);
  281. m_pv = (T**)malloc(m_dwReal * sizeof(T*));
  282. }
  283. void Destroy()
  284. {
  285. ASSERT(IsValid());
  286. CLocalLock<_PutGuard> locallock1(m_csPut);
  287. CLocalLock<_GetGuard> locallock2(m_csGet);
  288. free((void*)m_pv);
  289. m_pv = nullptr;
  290. m_dwReal = 0;
  291. m_seqPut = 0;
  292. m_seqGet = 0;
  293. }
  294. private:
  295. CRingBuffer(const CRingBuffer&);
  296. CRingBuffer operator = (const CRingBuffer&);
  297. private:
  298. DWORD m_dwReal;
  299. T** m_pv;
  300. char pack1[PACK_SIZE_OF(T**)];
  301. volatile ULONGLONG m_seqPut;
  302. char pack4[PACK_SIZE_OF(ULONGLONG)];
  303. volatile ULONGLONG m_seqGet;
  304. char pack5[PACK_SIZE_OF(ULONGLONG)];
  305. _PutGuard m_csPut;
  306. char pack2[PACK_SIZE_OF(_PutGuard)];
  307. _GetGuard m_csGet;
  308. char pack3[PACK_SIZE_OF(_GetGuard)];
  309. };
  310. typedef CRingBuffer<void, CCriSec, CCriSec> CCSRingBuffer;
  311. typedef CRingBuffer<void, CInterCriSec, CInterCriSec> CICSRingBuffer;
  312. typedef CRingBuffer<void, CSpinGuard, CSpinGuard> CSGRingBuffer;
  313. typedef CRingBuffer<void, CFakeGuard, CFakeGuard> CFKRingBuffer;
  314. // ------------------------------------------------------------------------------------------------------------- //
  315. template <class T, class index_type = DWORD, bool adjust_index = false> class CRingCache
  316. {
  317. public:
  318. enum EnGetResult {GR_FAIL = -1, GR_INVALID = 0, GR_VALID = 1};
  319. typedef T* TPTR;
  320. typedef volatile T* VTPTR;
  321. typedef unordered_set<index_type> IndexSet;
  322. typedef typename IndexSet::const_iterator IndexSetCI;
  323. typedef typename IndexSet::iterator IndexSetI;
  324. static TPTR const E_EMPTY;
  325. static TPTR const E_LOCKED;
  326. static TPTR const E_MAX_STATUS;
  327. public:
  328. static index_type& INDEX_INC(index_type& dwIndex) {if(adjust_index) ++dwIndex; return dwIndex;}
  329. static index_type& INDEX_DEC(index_type& dwIndex) {if(adjust_index) --dwIndex; return dwIndex;}
  330. private:
  331. index_type& INDEX_V2R(index_type& dwIndex) {dwIndex %= m_dwSize; if(dwIndex == 0) dwIndex = m_dwSize; return dwIndex;}
  332. VTPTR& INDEX_VAL(index_type dwIndex) {return *(m_pv + dwIndex);}
  333. public:
  334. BOOL Put(TPTR pElement, index_type& dwIndex)
  335. {
  336. ASSERT(pElement != nullptr);
  337. if(!IsValid()) return FALSE;
  338. BOOL isOK = FALSE;
  339. while(true)
  340. {
  341. if(!HasSpace())
  342. break;
  343. DWORD dwCurSeq = m_dwCurSeq;
  344. index_type dwCurIndex = dwCurSeq % m_dwSize;
  345. VTPTR& pValue = INDEX_VAL(dwCurIndex);
  346. if(pValue == E_EMPTY)
  347. {
  348. if(::InterlockedCompareExchangePointer((volatile PVOID*)&pValue, pElement, E_EMPTY) == E_EMPTY)
  349. {
  350. ::InterlockedIncrement(&m_dwCount);
  351. ::InterlockedCompareExchange(&m_dwCurSeq, dwCurSeq + 1, dwCurSeq);
  352. dwIndex = INDEX_INC(dwCurIndex);
  353. isOK = TRUE;
  354. if(pElement != E_LOCKED)
  355. EmplaceIndex(dwIndex);
  356. break;
  357. }
  358. }
  359. ::InterlockedCompareExchange(&m_dwCurSeq, dwCurSeq + 1, dwCurSeq);
  360. }
  361. return isOK;
  362. }
  363. EnGetResult GetEx(index_type dwIndex, TPTR* ppElement)
  364. {
  365. return Get(INDEX_V2R(dwIndex), ppElement);
  366. }
  367. EnGetResult Get(index_type dwIndex, TPTR* ppElement)
  368. {
  369. ASSERT(dwIndex <= m_dwSize);
  370. ASSERT(ppElement != nullptr);
  371. if(!IsValid() || INDEX_DEC(dwIndex) >= m_dwSize)
  372. {
  373. *ppElement = nullptr;
  374. return GR_FAIL;
  375. }
  376. *ppElement = (TPTR)INDEX_VAL(dwIndex);
  377. return IsValidElement(*ppElement) ? GR_VALID : GR_INVALID;
  378. }
  379. BOOL SetEx(index_type dwIndex, TPTR pElement, TPTR* ppOldElement = nullptr)
  380. {
  381. return Set(INDEX_V2R(dwIndex), pElement, ppOldElement);
  382. }
  383. BOOL Set(index_type dwIndex, TPTR pElement, TPTR* ppOldElement = nullptr)
  384. {
  385. TPTR pElement2 = nullptr;
  386. if(Get(dwIndex, &pElement2) == GR_FAIL)
  387. return FALSE;
  388. if(ppOldElement != nullptr)
  389. *ppOldElement = pElement2;
  390. if(pElement == pElement2)
  391. return FALSE;
  392. int f1 = 0;
  393. int f2 = 0;
  394. if(pElement == E_EMPTY)
  395. {
  396. if(pElement2 == E_LOCKED)
  397. f1 = -1;
  398. else
  399. f1 = f2 = -1;
  400. }
  401. else if(pElement == E_LOCKED)
  402. {
  403. if(pElement2 == E_EMPTY)
  404. f1 = 1;
  405. else
  406. f2 = -1;
  407. }
  408. else
  409. {
  410. if(pElement2 == E_EMPTY)
  411. f1 = f2 = 1;
  412. else if(pElement2 == E_LOCKED)
  413. f2 = 1;
  414. }
  415. BOOL bSetValueFirst = (f1 + f2 >= 0);
  416. index_type dwOuterIndex = dwIndex;
  417. INDEX_DEC(dwIndex);
  418. if(bSetValueFirst) INDEX_VAL(dwIndex) = pElement;
  419. if(f1 > 0) ::InterlockedIncrement(&m_dwCount);
  420. if(f2 != 0) (f2 > 0) ? EmplaceIndex(dwOuterIndex) : EraseIndex(dwOuterIndex);
  421. if(f1 < 0) ::InterlockedDecrement(&m_dwCount);
  422. if(!bSetValueFirst) INDEX_VAL(dwIndex) = pElement;
  423. ASSERT(Spaces() <= Size());
  424. return TRUE;
  425. }
  426. BOOL RemoveEx(index_type dwIndex, TPTR* ppElement = nullptr)
  427. {
  428. return Remove(INDEX_V2R(dwIndex), ppElement);
  429. }
  430. BOOL Remove(index_type dwIndex, TPTR* ppElement = nullptr)
  431. {
  432. return Set(dwIndex, E_EMPTY, ppElement);
  433. }
  434. BOOL AcquireLock(index_type& dwIndex)
  435. {
  436. return Put(E_LOCKED, dwIndex);
  437. }
  438. BOOL ReleaseLock(index_type dwIndex, TPTR pElement)
  439. {
  440. ASSERT(pElement == nullptr || IsValidElement(pElement));
  441. TPTR pElement2 = nullptr;
  442. Get(dwIndex, &pElement2);
  443. ASSERT(pElement2 == E_LOCKED);
  444. if(pElement2 != E_LOCKED)
  445. return FALSE;
  446. return Set(dwIndex, pElement);
  447. }
  448. public:
  449. void Reset(DWORD dwSize = 0)
  450. {
  451. if(IsValid())
  452. Destroy();
  453. if(dwSize > 0)
  454. Create(dwSize);
  455. }
  456. BOOL GetAllElementIndexes(index_type ids[], DWORD& dwCount, BOOL bCopy = TRUE)
  457. {
  458. if(ids == nullptr || dwCount == 0)
  459. {
  460. dwCount = Elements();
  461. return FALSE;
  462. }
  463. IndexSet* pIndexes = nullptr;
  464. IndexSet indexes;
  465. if(bCopy)
  466. pIndexes = &CopyIndexes(indexes);
  467. else
  468. pIndexes = &m_indexes;
  469. BOOL isOK = FALSE;
  470. DWORD dwSize = (DWORD)pIndexes->size();
  471. if(dwSize > 0 && dwSize <= dwCount)
  472. {
  473. IndexSetCI it = pIndexes->begin();
  474. IndexSetCI end = pIndexes->end();
  475. for(int i = 0; it != end; ++it, ++i)
  476. ids[i] = *it;
  477. isOK = TRUE;
  478. }
  479. dwCount = dwSize;
  480. return isOK;
  481. }
  482. unique_ptr<index_type[]> GetAllElementIndexes(DWORD& dwCount, BOOL bCopy = TRUE)
  483. {
  484. IndexSet* pIndexes = nullptr;
  485. IndexSet indexes;
  486. if(bCopy)
  487. pIndexes = &CopyIndexes(indexes);
  488. else
  489. pIndexes = &m_indexes;
  490. unique_ptr<index_type[]> ids;
  491. dwCount = (DWORD)pIndexes->size();
  492. if(dwCount > 0)
  493. {
  494. ids.reset(new index_type[dwCount]);
  495. IndexSetCI it = pIndexes->begin();
  496. IndexSetCI end = pIndexes->end();
  497. for(int i = 0; it != end; ++it, ++i)
  498. ids[i] = *it;
  499. }
  500. return ids;
  501. }
  502. static BOOL IsValidElement(TPTR pElement) {return pElement > E_MAX_STATUS;}
  503. DWORD Size () {return m_dwSize;}
  504. DWORD Elements () {return (DWORD)m_indexes.size();}
  505. DWORD Spaces () {return m_dwSize - m_dwCount;}
  506. BOOL HasSpace () {return m_dwCount < m_dwSize;}
  507. BOOL IsEmpty () {return m_dwCount == 0;}
  508. BOOL IsValid () {return m_pv != nullptr;}
  509. private:
  510. void Create(DWORD dwSize)
  511. {
  512. ASSERT(!IsValid() && dwSize > 0);
  513. m_dwCurSeq = 0;
  514. m_dwCount = 0;
  515. m_dwSize = dwSize;
  516. m_pv = (VTPTR*)malloc(m_dwSize * sizeof(TPTR));
  517. ::ZeroMemory(m_pv, m_dwSize * sizeof(TPTR));
  518. }
  519. void Destroy()
  520. {
  521. ASSERT(IsValid());
  522. m_indexes.clear();
  523. free((void*)m_pv);
  524. m_pv = nullptr;
  525. m_dwSize = 0;
  526. m_dwCount = 0;
  527. m_dwCurSeq = 0;
  528. }
  529. IndexSet& CopyIndexes(IndexSet& indexes)
  530. {
  531. {
  532. CReadLock locallock(m_cs);
  533. indexes = m_indexes;
  534. }
  535. return indexes;
  536. }
  537. void EmplaceIndex(index_type dwIndex)
  538. {
  539. CWriteLock locallock(m_cs);
  540. m_indexes.emplace(dwIndex);
  541. }
  542. void EraseIndex(index_type dwIndex)
  543. {
  544. CWriteLock locallock(m_cs);
  545. m_indexes.erase(dwIndex);
  546. }
  547. public:
  548. CRingCache (DWORD dwSize = 0)
  549. : m_pv (nullptr)
  550. , m_dwSize (0)
  551. , m_dwCount (0)
  552. , m_dwCurSeq(0)
  553. {
  554. Reset(dwSize);
  555. }
  556. ~CRingCache()
  557. {
  558. Reset(0);
  559. }
  560. private:
  561. CRingCache(const CRingCache&);
  562. CRingCache operator = (const CRingCache&);
  563. private:
  564. DWORD m_dwSize;
  565. VTPTR* m_pv;
  566. char pack1[PACK_SIZE_OF(VTPTR*)];
  567. volatile DWORD m_dwCurSeq;
  568. char pack2[PACK_SIZE_OF(DWORD)];
  569. volatile DWORD m_dwCount;
  570. char pack3[PACK_SIZE_OF(DWORD)];
  571. CSimpleRWLock m_cs;
  572. IndexSet m_indexes;
  573. };
  574. template <class T, class index_type, bool adjust_index> T* const CRingCache<T, index_type, adjust_index>::E_EMPTY = (T*)0x00;
  575. template <class T, class index_type, bool adjust_index> T* const CRingCache<T, index_type, adjust_index>::E_LOCKED = (T*)0x01;
  576. template <class T, class index_type, bool adjust_index> T* const CRingCache<T, index_type, adjust_index>::E_MAX_STATUS = (T*)0x0F;
  577. // ------------------------------------------------------------------------------------------------------------- //
  578. template <class T, class index_type = DWORD, bool adjust_index = false> class CRingCache2
  579. {
  580. public:
  581. enum EnGetResult {GR_FAIL = -1, GR_INVALID = 0, GR_VALID = 1};
  582. typedef T* TPTR;
  583. typedef volatile T* VTPTR;
  584. typedef unordered_set<index_type> IndexSet;
  585. typedef typename IndexSet::const_iterator IndexSetCI;
  586. typedef typename IndexSet::iterator IndexSetI;
  587. static TPTR const E_EMPTY;
  588. static TPTR const E_LOCKED;
  589. static TPTR const E_MAX_STATUS;
  590. static DWORD const MAX_SIZE;
  591. public:
  592. static index_type& INDEX_INC(index_type& dwIndex) {if(adjust_index) ++dwIndex; return dwIndex;}
  593. static index_type& INDEX_DEC(index_type& dwIndex) {if(adjust_index) --dwIndex; return dwIndex;}
  594. index_type& INDEX_R2V(index_type& dwIndex) {dwIndex += *(m_px + dwIndex) * m_dwSize; return dwIndex;}
  595. BOOL INDEX_V2R(index_type& dwIndex)
  596. {
  597. index_type m = dwIndex % m_dwSize;
  598. BYTE x = *(m_px + m);
  599. if(dwIndex / m_dwSize != x)
  600. return FALSE;
  601. dwIndex = m;
  602. return TRUE;
  603. }
  604. private:
  605. VTPTR& INDEX_VAL(index_type dwIndex) {return *(m_pv + dwIndex);}
  606. public:
  607. BOOL Put(TPTR pElement, index_type& dwIndex)
  608. {
  609. ASSERT(pElement != nullptr);
  610. if(!IsValid()) return FALSE;
  611. BOOL isOK = FALSE;
  612. while(true)
  613. {
  614. if(!HasSpace())
  615. break;
  616. DWORD dwCurSeq = m_dwCurSeq;
  617. index_type dwCurIndex = dwCurSeq % m_dwSize;
  618. VTPTR& pValue = INDEX_VAL(dwCurIndex);
  619. if(pValue == E_EMPTY)
  620. {
  621. if(::InterlockedCompareExchangePointer((volatile PVOID*)&pValue, pElement, E_EMPTY) == E_EMPTY)
  622. {
  623. ::InterlockedIncrement(&m_dwCount);
  624. ::InterlockedCompareExchange(&m_dwCurSeq, dwCurSeq + 1, dwCurSeq);
  625. dwIndex = INDEX_INC(INDEX_R2V(dwCurIndex));
  626. isOK = TRUE;
  627. if(pElement != E_LOCKED)
  628. EmplaceIndex(dwIndex);
  629. break;
  630. }
  631. }
  632. ::InterlockedCompareExchange(&m_dwCurSeq, dwCurSeq + 1, dwCurSeq);
  633. }
  634. return isOK;
  635. }
  636. EnGetResult Get(index_type dwIndex, TPTR* ppElement, index_type* pdwRealIndex = nullptr)
  637. {
  638. ASSERT(ppElement != nullptr);
  639. if(!IsValid() || !INDEX_V2R(INDEX_DEC(dwIndex)))
  640. {
  641. *ppElement = nullptr;
  642. return GR_FAIL;
  643. }
  644. *ppElement = (TPTR)INDEX_VAL(dwIndex);
  645. if(pdwRealIndex) *pdwRealIndex = dwIndex;
  646. return IsValidElement(*ppElement) ? GR_VALID : GR_INVALID;
  647. }
  648. BOOL Set(index_type dwIndex, TPTR pElement, TPTR* ppOldElement = nullptr, index_type* pdwRealIndex = nullptr)
  649. {
  650. TPTR pElement2 = nullptr;
  651. if(pdwRealIndex == nullptr)
  652. pdwRealIndex = (index_type*)_alloca(sizeof(index_type));
  653. if(Get(dwIndex, &pElement2, pdwRealIndex) == GR_FAIL)
  654. return FALSE;
  655. if(ppOldElement != nullptr)
  656. *ppOldElement = pElement2;
  657. if(pElement == pElement2)
  658. return FALSE;
  659. int f1 = 0;
  660. int f2 = 0;
  661. if(pElement == E_EMPTY)
  662. {
  663. if(pElement2 == E_LOCKED)
  664. f1 = -1;
  665. else
  666. f1 = f2 = -1;
  667. }
  668. else if(pElement == E_LOCKED)
  669. {
  670. if(pElement2 == E_EMPTY)
  671. f1 = 1;
  672. else
  673. f2 = -1;
  674. }
  675. else
  676. {
  677. if(pElement2 == E_EMPTY)
  678. f1 = f2 = 1;
  679. else if(pElement2 == E_LOCKED)
  680. f2 = 1;
  681. }
  682. BOOL bSetValueFirst = (f1 + f2 >= 0);
  683. index_type dwRealIndex = *pdwRealIndex;
  684. if(bSetValueFirst) INDEX_VAL(dwRealIndex) = pElement;
  685. if(f1 > 0) ::InterlockedIncrement(&m_dwCount);
  686. if(f2 != 0) (f2 > 0) ? EmplaceIndex(dwIndex) : EraseIndex(dwIndex);
  687. if(f1 < 0) {::InterlockedDecrement(&m_dwCount); ++(*(m_px + dwRealIndex));}
  688. if(!bSetValueFirst) INDEX_VAL(dwRealIndex) = pElement;
  689. ASSERT(Spaces() <= Size());
  690. return TRUE;
  691. }
  692. BOOL Remove(index_type dwIndex, TPTR* ppElement = nullptr)
  693. {
  694. return Set(dwIndex, E_EMPTY, ppElement);
  695. }
  696. BOOL AcquireLock(index_type& dwIndex)
  697. {
  698. return Put(E_LOCKED, dwIndex);
  699. }
  700. BOOL ReleaseLock(index_type dwIndex, TPTR pElement)
  701. {
  702. ASSERT(pElement == nullptr || IsValidElement(pElement));
  703. TPTR pElement2 = nullptr;
  704. Get(dwIndex, &pElement2);
  705. ASSERT(pElement2 == E_LOCKED);
  706. if(pElement2 != E_LOCKED)
  707. return FALSE;
  708. return Set(dwIndex, pElement);
  709. }
  710. public:
  711. void Reset(DWORD dwSize = 0)
  712. {
  713. if(IsValid())
  714. Destroy();
  715. if(dwSize > 0)
  716. Create(dwSize);
  717. }
  718. BOOL GetAllElementIndexes(index_type ids[], DWORD& dwCount, BOOL bCopy = TRUE)
  719. {
  720. if(ids == nullptr || dwCount == 0)
  721. {
  722. dwCount = Elements();
  723. return FALSE;
  724. }
  725. IndexSet* pIndexes = nullptr;
  726. IndexSet indexes;
  727. if(bCopy)
  728. pIndexes = &CopyIndexes(indexes);
  729. else
  730. pIndexes = &m_indexes;
  731. BOOL isOK = FALSE;
  732. DWORD dwSize = (DWORD)pIndexes->size();
  733. if(dwSize > 0 && dwSize <= dwCount)
  734. {
  735. IndexSetCI it = pIndexes->begin();
  736. IndexSetCI end = pIndexes->end();
  737. for(int i = 0; it != end; ++it, ++i)
  738. ids[i] = *it;
  739. isOK = TRUE;
  740. }
  741. dwCount = dwSize;
  742. return isOK;
  743. }
  744. unique_ptr<index_type[]> GetAllElementIndexes(DWORD& dwCount, BOOL bCopy = TRUE)
  745. {
  746. IndexSet* pIndexes = nullptr;
  747. IndexSet indexes;
  748. if(bCopy)
  749. pIndexes = &CopyIndexes(indexes);
  750. else
  751. pIndexes = &m_indexes;
  752. unique_ptr<index_type[]> ids;
  753. dwCount = (DWORD)pIndexes->size();
  754. if(dwCount > 0)
  755. {
  756. ids.reset(new index_type[dwCount]);
  757. IndexSetCI it = pIndexes->begin();
  758. IndexSetCI end = pIndexes->end();
  759. for(int i = 0; it != end; ++it, ++i)
  760. ids[i] = *it;
  761. }
  762. return ids;
  763. }
  764. static BOOL IsValidElement(TPTR pElement) {return pElement > E_MAX_STATUS;}
  765. DWORD Size () {return m_dwSize;}
  766. DWORD Elements () {return (DWORD)m_indexes.size();}
  767. DWORD Spaces () {return m_dwSize - m_dwCount;}
  768. BOOL HasSpace () {return m_dwCount < m_dwSize;}
  769. BOOL IsEmpty () {return m_dwCount == 0;}
  770. BOOL IsValid () {return m_pv != nullptr;}
  771. private:
  772. void Create(DWORD dwSize)
  773. {
  774. ASSERT(!IsValid() && dwSize > 0 && dwSize <= MAX_SIZE);
  775. m_dwCurSeq = 0;
  776. m_dwCount = 0;
  777. m_dwSize = dwSize;
  778. m_pv = (VTPTR*)malloc(m_dwSize * sizeof(TPTR));
  779. m_px = (BYTE*)malloc(m_dwSize * sizeof(BYTE));
  780. ::ZeroMemory(m_pv, m_dwSize * sizeof(TPTR));
  781. ::ZeroMemory(m_px, m_dwSize * sizeof(BYTE));
  782. }
  783. void Destroy()
  784. {
  785. ASSERT(IsValid());
  786. m_indexes.clear();
  787. free((void*)m_pv);
  788. free((void*)m_px);
  789. m_pv = nullptr;
  790. m_px = nullptr;
  791. m_dwSize = 0;
  792. m_dwCount = 0;
  793. m_dwCurSeq = 0;
  794. }
  795. IndexSet& CopyIndexes(IndexSet& indexes)
  796. {
  797. {
  798. CReadLock locallock(m_cs);
  799. indexes = m_indexes;
  800. }
  801. return indexes;
  802. }
  803. void EmplaceIndex(index_type dwIndex)
  804. {
  805. CWriteLock locallock(m_cs);
  806. m_indexes.emplace(dwIndex);
  807. }
  808. void EraseIndex(index_type dwIndex)
  809. {
  810. CWriteLock locallock(m_cs);
  811. m_indexes.erase(dwIndex);
  812. }
  813. public:
  814. CRingCache2 (DWORD dwSize = 0)
  815. : m_pv (nullptr)
  816. , m_px (nullptr)
  817. , m_dwSize (0)
  818. , m_dwCount (0)
  819. , m_dwCurSeq(0)
  820. {
  821. Reset(dwSize);
  822. }
  823. ~CRingCache2()
  824. {
  825. Reset(0);
  826. }
  827. private:
  828. CRingCache2(const CRingCache2&);
  829. CRingCache2 operator = (const CRingCache2&);
  830. private:
  831. DWORD m_dwSize;
  832. VTPTR* m_pv;
  833. char pack1[PACK_SIZE_OF(VTPTR*)];
  834. BYTE* m_px;
  835. char pack2[PACK_SIZE_OF(BYTE*)];
  836. volatile DWORD m_dwCurSeq;
  837. char pack3[PACK_SIZE_OF(DWORD)];
  838. volatile DWORD m_dwCount;
  839. char pack4[PACK_SIZE_OF(DWORD)];
  840. CSimpleRWLock m_cs;
  841. IndexSet m_indexes;
  842. };
  843. template <class T, class index_type, bool adjust_index> T* const CRingCache2<T, index_type, adjust_index>::E_EMPTY = (T*)0x00;
  844. template <class T, class index_type, bool adjust_index> T* const CRingCache2<T, index_type, adjust_index>::E_LOCKED = (T*)0x01;
  845. template <class T, class index_type, bool adjust_index> T* const CRingCache2<T, index_type, adjust_index>::E_MAX_STATUS = (T*)0x0F;
  846. template <class T, class index_type, bool adjust_index> DWORD const CRingCache2<T, index_type, adjust_index>::MAX_SIZE =
  847. #if !defined(_WIN64)
  848. 0x00FFFFFF
  849. #else
  850. 0xFFFFFFFF
  851. #endif
  852. ;
  853. // ------------------------------------------------------------------------------------------------------------- //
  854. template <class T> class CRingPool
  855. {
  856. private:
  857. typedef T* TPTR;
  858. typedef volatile T* VTPTR;
  859. static TPTR const E_EMPTY;
  860. static TPTR const E_LOCKED;
  861. static TPTR const E_RELEASED;
  862. static TPTR const E_OCCUPIED;
  863. static TPTR const E_MAX_STATUS;
  864. private:
  865. VTPTR& INDEX_VAL(DWORD dwIndex) {return *(m_pv + dwIndex);}
  866. public:
  867. BOOL TryPut(TPTR pElement)
  868. {
  869. ASSERT(pElement != nullptr);
  870. if(!IsValid()) return FALSE;
  871. BOOL isOK = FALSE;
  872. while(true)
  873. {
  874. BOOL bOccupy = FALSE;
  875. DWORD seqPut = m_seqPut;
  876. if(!HasPutSpace(seqPut))
  877. break;
  878. DWORD dwIndex = seqPut % m_dwSize;
  879. VTPTR& pValue = INDEX_VAL(dwIndex);
  880. if(pValue == E_RELEASED)
  881. {
  882. if(::InterlockedCompareExchangePointer((volatile PVOID*)&pValue, E_OCCUPIED, E_RELEASED) == E_RELEASED)
  883. bOccupy = TRUE;
  884. else
  885. continue;
  886. }
  887. if(pValue == E_EMPTY || bOccupy)
  888. {
  889. if(::InterlockedCompareExchange(&m_seqPut, seqPut + 1, seqPut) == seqPut)
  890. {
  891. pValue = pElement;
  892. isOK = TRUE;
  893. break;
  894. }
  895. }
  896. else if(pValue == E_LOCKED)
  897. break;
  898. }
  899. return isOK;
  900. }
  901. BOOL TryGet(TPTR* ppElement)
  902. {
  903. ASSERT(ppElement != nullptr);
  904. if(!IsValid()) return FALSE;
  905. BOOL isOK = FALSE;
  906. while(true)
  907. {
  908. DWORD seqGet = m_seqGet;
  909. if(!HasGetSpace(seqGet))
  910. break;
  911. DWORD dwIndex = seqGet % m_dwSize;
  912. VTPTR& pValue = INDEX_VAL(dwIndex);
  913. if(pValue == E_LOCKED)
  914. break;
  915. else if(pValue != E_EMPTY && pValue != E_RELEASED && pValue != E_OCCUPIED)
  916. {
  917. if(::InterlockedCompareExchange(&m_seqGet, seqGet + 1, seqGet) == seqGet)
  918. {
  919. ASSERT(pValue > E_MAX_STATUS);
  920. *(ppElement) = (TPTR)pValue;
  921. pValue = E_EMPTY;
  922. isOK = TRUE;
  923. break;
  924. }
  925. }
  926. }
  927. return isOK;
  928. }
  929. BOOL TryLock(TPTR* ppElement, DWORD& dwIndex)
  930. {
  931. ASSERT(ppElement != nullptr);
  932. if(!IsValid()) return FALSE;
  933. BOOL isOK = FALSE;
  934. while(true)
  935. {
  936. DWORD seqGet = m_seqGet;
  937. if(!HasGetSpace(seqGet))
  938. break;
  939. dwIndex = seqGet % m_dwSize;
  940. VTPTR& pValue = INDEX_VAL(dwIndex);
  941. if(pValue == E_LOCKED)
  942. break;
  943. else if(pValue != E_EMPTY && pValue != E_RELEASED && pValue != E_OCCUPIED)
  944. {
  945. if(::InterlockedCompareExchange(&m_seqGet, seqGet + 1, seqGet) == seqGet)
  946. {
  947. ASSERT(pValue > E_MAX_STATUS);
  948. *(ppElement) = (TPTR)pValue;
  949. pValue = E_LOCKED;
  950. isOK = TRUE;
  951. break;
  952. }
  953. }
  954. }
  955. return isOK;
  956. }
  957. BOOL ReleaseLock(TPTR pElement, DWORD dwIndex)
  958. {
  959. ASSERT(dwIndex < m_dwSize);
  960. ASSERT(pElement == nullptr || pElement > E_MAX_STATUS);
  961. if(!IsValid()) return FALSE;
  962. VTPTR& pValue = INDEX_VAL(dwIndex);
  963. VERIFY(pValue == E_LOCKED);
  964. if(pElement != nullptr)
  965. {
  966. for(DWORD i = 0; ; i++)
  967. {
  968. if(TryPut(pElement))
  969. break;
  970. DWORD dwPutIndex = m_seqPut % m_dwSize;
  971. if(dwIndex == dwPutIndex)
  972. {
  973. pValue = pElement;
  974. ::InterlockedIncrement(&m_seqPut);
  975. return TRUE;
  976. }
  977. ::YieldThread(i);
  978. }
  979. }
  980. pValue = E_RELEASED;
  981. return TRUE;
  982. }
  983. public:
  984. void Reset(DWORD dwSize = 0)
  985. {
  986. if(IsValid())
  987. Destroy();
  988. if(dwSize > 0)
  989. Create(dwSize);
  990. }
  991. DWORD Size() {return m_dwSize;}
  992. DWORD Elements() {return m_seqPut - m_seqGet;}
  993. BOOL IsFull() {return Elements() == Size();}
  994. BOOL IsEmpty() {return Elements() == 0;}
  995. BOOL IsValid() {return m_pv != nullptr;}
  996. private:
  997. BOOL HasPutSpace(DWORD seqPut)
  998. {
  999. return ((int)(seqPut - m_seqGet) < (int)m_dwSize);
  1000. }
  1001. BOOL HasGetSpace(DWORD seqGet)
  1002. {
  1003. return ((int)(m_seqPut - seqGet) > 0);
  1004. }
  1005. void Create(DWORD dwSize)
  1006. {
  1007. ASSERT(!IsValid() && dwSize > 0);
  1008. m_seqPut = 0;
  1009. m_seqGet = 0;
  1010. m_dwSize = dwSize;
  1011. m_pv = (VTPTR*)malloc(m_dwSize * sizeof(TPTR));
  1012. ::ZeroMemory(m_pv, m_dwSize * sizeof(TPTR));
  1013. }
  1014. void Destroy()
  1015. {
  1016. ASSERT(IsValid());
  1017. free((void*)m_pv);
  1018. m_pv = nullptr;
  1019. m_dwSize = 0;
  1020. m_seqPut = 0;
  1021. m_seqGet = 0;
  1022. }
  1023. public:
  1024. CRingPool(DWORD dwSize = 0)
  1025. : m_pv(nullptr)
  1026. , m_dwSize(0)
  1027. , m_seqPut(0)
  1028. , m_seqGet(0)
  1029. {
  1030. Reset(dwSize);
  1031. }
  1032. ~CRingPool()
  1033. {
  1034. Reset(0);
  1035. }
  1036. private:
  1037. CRingPool(const CRingPool&);
  1038. CRingPool operator = (const CRingPool&);
  1039. private:
  1040. DWORD m_dwSize;
  1041. VTPTR* m_pv;
  1042. char pack1[PACK_SIZE_OF(VTPTR*)];
  1043. volatile DWORD m_seqPut;
  1044. char pack2[PACK_SIZE_OF(DWORD)];
  1045. volatile DWORD m_seqGet;
  1046. char pack3[PACK_SIZE_OF(DWORD)];
  1047. };
  1048. template <class T> T* const CRingPool<T>::E_EMPTY = (T*)0x00;
  1049. template <class T> T* const CRingPool<T>::E_LOCKED = (T*)0x01;
  1050. template <class T> T* const CRingPool<T>::E_RELEASED = (T*)0x02;
  1051. template <class T> T* const CRingPool<T>::E_OCCUPIED = (T*)0x03;
  1052. template <class T> T* const CRingPool<T>::E_MAX_STATUS = (T*)0x0F;
  1053. // ------------------------------------------------------------------------------------------------------------- //
  1054. template <class T> class CCASQueue
  1055. {
  1056. private:
  1057. struct Node;
  1058. typedef Node* NPTR;
  1059. typedef volatile Node* VNPTR;
  1060. typedef volatile ULONG VLONG;
  1061. struct Node
  1062. {
  1063. T* pValue;
  1064. VNPTR pNext;
  1065. Node(T* val, NPTR next = nullptr)
  1066. : pValue(val), pNext(next)
  1067. {
  1068. }
  1069. };
  1070. public:
  1071. void PushBack(T* pVal)
  1072. {
  1073. ASSERT(pVal != nullptr);
  1074. VNPTR pTail = nullptr;
  1075. NPTR pNode = new Node(pVal);
  1076. while(true)
  1077. {
  1078. pTail = m_pTail;
  1079. if(::InterlockedCompareExchangePointer((volatile PVOID*)&m_pTail, (PVOID)pNode, (PVOID)pTail) == pTail)
  1080. {
  1081. pTail->pNext = pNode;
  1082. break;
  1083. }
  1084. }
  1085. ::InterlockedIncrement(&m_lSize);
  1086. }
  1087. void UnsafePushBack(T* pVal)
  1088. {
  1089. ASSERT(pVal != nullptr);
  1090. NPTR pNode = new Node(pVal);
  1091. m_pTail->pNext = pNode;
  1092. m_pTail = pNode;
  1093. ::InterlockedIncrement(&m_lSize);
  1094. }
  1095. BOOL PopFront(T** ppVal)
  1096. {
  1097. ASSERT(ppVal != nullptr);
  1098. if(IsEmpty())
  1099. return FALSE;
  1100. BOOL isOK = FALSE;
  1101. NPTR pHead = nullptr;
  1102. NPTR pNext = nullptr;
  1103. while(true)
  1104. {
  1105. while(::InterlockedCompareExchange(&m_lLock, 1, 0) != 0)
  1106. ::YieldProcessor();
  1107. pHead = (NPTR)m_pHead;
  1108. pNext = (NPTR)pHead->pNext;
  1109. if(pNext == nullptr)
  1110. {
  1111. m_lLock = 0;
  1112. break;
  1113. }
  1114. *ppVal = pNext->pValue;
  1115. m_pHead = pNext;
  1116. m_lLock = 0;
  1117. isOK = TRUE;
  1118. ::InterlockedDecrement(&m_lSize);
  1119. delete pHead;
  1120. break;
  1121. }
  1122. return isOK;
  1123. }
  1124. BOOL UnsafePopFront(T** ppVal)
  1125. {
  1126. if(!UnsafePeekFront(ppVal))
  1127. return FALSE;
  1128. NPTR pHead = (NPTR)m_pHead;
  1129. NPTR pNext = (NPTR)pHead->pNext;
  1130. m_pHead = pNext;
  1131. ::InterlockedDecrement(&m_lSize);
  1132. delete pHead;
  1133. return TRUE;
  1134. }
  1135. BOOL UnsafePeekFront(T** ppVal)
  1136. {
  1137. ASSERT(ppVal != nullptr);
  1138. NPTR pNext = (NPTR)m_pHead->pNext;
  1139. if(pNext == nullptr)
  1140. return FALSE;
  1141. *ppVal = pNext->pValue;
  1142. return TRUE;
  1143. }
  1144. public:
  1145. ULONG Size() {return m_lSize;}
  1146. BOOL IsEmpty() {return m_lSize == 0;}
  1147. public:
  1148. CCASQueue() : m_lLock(0), m_lSize(0)
  1149. {
  1150. NPTR pHead = new Node(nullptr);
  1151. m_pHead = m_pTail = pHead;
  1152. }
  1153. ~CCASQueue()
  1154. {
  1155. ASSERT(m_lLock == 0);
  1156. ASSERT(m_lSize == 0);
  1157. ASSERT(m_pHead != nullptr);
  1158. ASSERT(m_pHead->pNext == nullptr);
  1159. while(m_pHead != nullptr)
  1160. {
  1161. VNPTR pNode = m_pHead->pNext;
  1162. delete m_pHead;
  1163. m_pHead = pNode;
  1164. }
  1165. }
  1166. private:
  1167. VLONG m_lLock;
  1168. VLONG m_lSize;
  1169. VNPTR m_pHead;
  1170. VNPTR m_pTail;
  1171. };
  1172. #if !defined (_WIN64)
  1173. #pragma pack(pop)
  1174. #endif