| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731 |
- /*
- * Copyright: JessMA Open Source (ldcsaa@gmail.com)
- *
- * Author : Bruce Liang
- * Website : https://github.com/ldcsaa
- * Project : https://github.com/ldcsaa/HP-Socket
- * Blog : http://www.cnblogs.com/ldcsaa
- * Wiki : http://www.oschina.net/p/hp-socket
- * QQ Group : 44636872, 75375912
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #pragma once
- #include "hpsocket/GlobalDef.h"
- #include "Singleton.h"
- #include "STLHelper.h"
- #include "FuncHelper.h"
- #include "RWLock.h"
- using namespace std;
- #define CACHE_LINE 64
- #define PACK_SIZE_OF(T) (CACHE_LINE - sizeof(T) % CACHE_LINE)
- #if __WORDSIZE == 32
- #pragma pack(push, 4)
- #endif
- // ------------------------------------------------------------------------------------------------------------- //
- template <class T, class index_type = DWORD, bool adjust_index = false> class CRingCache
- {
- public:
- enum EnGetResult {GR_FAIL = -1, GR_INVALID = 0, GR_VALID = 1};
- typedef T* TPTR;
- typedef volatile T* VTPTR;
- typedef unordered_set<index_type> IndexSet;
- typedef typename IndexSet::const_iterator IndexSetCI;
- typedef typename IndexSet::iterator IndexSetI;
- static TPTR const E_EMPTY;
- static TPTR const E_LOCKED;
- static TPTR const E_MAX_STATUS;
- public:
- static index_type& INDEX_INC(index_type& dwIndex) {if(adjust_index) ++dwIndex; return dwIndex;}
- static index_type& INDEX_DEC(index_type& dwIndex) {if(adjust_index) --dwIndex; return dwIndex;}
- private:
- index_type& INDEX_V2R(index_type& dwIndex) {dwIndex %= m_dwSize; if(dwIndex == 0) dwIndex = m_dwSize; return dwIndex;}
- VTPTR& INDEX_VAL(index_type dwIndex) {return *(m_pv + dwIndex);}
- public:
- BOOL Put(TPTR pElement, index_type& dwIndex)
- {
- ASSERT(pElement != nullptr);
- if(!IsValid()) return FALSE;
- BOOL isOK = FALSE;
- while(true)
- {
- if(!HasSpace())
- break;
- DWORD dwCurSeq = m_dwCurSeq;
- index_type dwCurIndex = dwCurSeq % m_dwSize;
- VTPTR& pValue = INDEX_VAL(dwCurIndex);
- if(pValue == E_EMPTY)
- {
- if(::InterlockedCompareExchangePointer(&pValue, pElement, E_EMPTY) == E_EMPTY)
- {
- ::InterlockedIncrement(&m_dwCount);
- ::InterlockedCompareExchange(&m_dwCurSeq, dwCurSeq + 1, dwCurSeq);
- dwIndex = INDEX_INC(dwCurIndex);
- isOK = TRUE;
- if(pElement != E_LOCKED)
- EmplaceIndex(dwIndex);
- break;
- }
- }
- ::InterlockedCompareExchange(&m_dwCurSeq, dwCurSeq + 1, dwCurSeq);
- }
- return isOK;
- }
- EnGetResult GetEx(index_type dwIndex, TPTR* ppElement)
- {
- return Get(INDEX_V2R(dwIndex), ppElement);
- }
- EnGetResult Get(index_type dwIndex, TPTR* ppElement)
- {
- ASSERT(dwIndex <= m_dwSize);
- ASSERT(ppElement != nullptr);
- if(!IsValid() || INDEX_DEC(dwIndex) >= m_dwSize)
- {
- *ppElement = nullptr;
- return GR_FAIL;
- }
- *ppElement = (TPTR)INDEX_VAL(dwIndex);
- return IsValidElement(*ppElement) ? GR_VALID : GR_INVALID;
- }
- BOOL SetEx(index_type dwIndex, TPTR pElement, TPTR* ppOldElement = nullptr)
- {
- return Set(INDEX_V2R(dwIndex), pElement, ppOldElement);
- }
- BOOL Set(index_type dwIndex, TPTR pElement, TPTR* ppOldElement = nullptr)
- {
- TPTR pElement2 = nullptr;
- if(Get(dwIndex, &pElement2) == GR_FAIL)
- return FALSE;
- if(ppOldElement != nullptr)
- *ppOldElement = pElement2;
- if(pElement == pElement2)
- return FALSE;
- int f1 = 0;
- int f2 = 0;
- if(pElement == E_EMPTY)
- {
- if(pElement2 == E_LOCKED)
- f1 = -1;
- else
- f1 = f2 = -1;
- }
- else if(pElement == E_LOCKED)
- {
- if(pElement2 == E_EMPTY)
- f1 = 1;
- else
- f2 = -1;
- }
- else
- {
- if(pElement2 == E_EMPTY)
- f1 = f2 = 1;
- else if(pElement2 == E_LOCKED)
- f2 = 1;
- }
- BOOL bSetValueFirst = (f1 + f2 >= 0);
- index_type dwOuterIndex = dwIndex;
- INDEX_DEC(dwIndex);
- if(bSetValueFirst) INDEX_VAL(dwIndex) = pElement;
- if(f1 > 0) ::InterlockedIncrement(&m_dwCount);
- if(f2 != 0) (f2 > 0) ? EmplaceIndex(dwOuterIndex) : EraseIndex(dwOuterIndex);
- if(f1 < 0) ::InterlockedDecrement(&m_dwCount);
- if(!bSetValueFirst) INDEX_VAL(dwIndex) = pElement;
- ASSERT(Spaces() <= Size());
- return TRUE;
- }
- BOOL RemoveEx(index_type dwIndex, TPTR* ppElement = nullptr)
- {
- return Remove(INDEX_V2R(dwIndex), ppElement);
- }
- BOOL Remove(index_type dwIndex, TPTR* ppElement = nullptr)
- {
- return Set(dwIndex, E_EMPTY, ppElement);
- }
- BOOL AcquireLock(index_type& dwIndex)
- {
- return Put(E_LOCKED, dwIndex);
- }
- BOOL ReleaseLock(index_type dwIndex, TPTR pElement)
- {
- ASSERT(pElement == nullptr || IsValidElement(pElement));
- TPTR pElement2 = nullptr;
- Get(dwIndex, &pElement2);
- ASSERT(pElement2 == E_LOCKED);
- if(pElement2 != E_LOCKED)
- return FALSE;
- return Set(dwIndex, pElement);
- }
- public:
- void Reset(DWORD dwSize = 0)
- {
- if(IsValid())
- Destroy();
- if(dwSize > 0)
- Create(dwSize);
- }
- BOOL GetAllElementIndexes(index_type ids[], DWORD& dwCount, BOOL bCopy = TRUE)
- {
- DWORD dwSize = Elements();
- if(ids == nullptr || dwCount == 0)
- {
- dwCount = dwSize;
- return FALSE;
- }
- if(dwSize == 0)
- {
- dwCount = 0;
- return TRUE;
- }
- IndexSet* pIndexes = &m_indexes;
- if(bCopy)
- {
- pIndexes = new IndexSet;
- CopyIndexes(*pIndexes);
- }
- DWORD i = 0;
- for(auto it = pIndexes->begin(), end = pIndexes->end(); i < dwCount && it != end; ++i, ++it)
- ids[i] = *it;
- if(bCopy) delete pIndexes;
- dwCount = i;
- return TRUE;
- }
-
- unique_ptr<index_type[]> GetAllElementIndexes(DWORD& dwCount, BOOL bCopy = TRUE)
- {
- dwCount = (DWORD)m_indexes.size();
- unique_ptr<index_type[]> ids(new index_type[dwCount]);
- if(dwCount > 0)
- GetAllElementIndexes(ids.get(), dwCount, bCopy);
- return ids;
- }
-
- IndexSet& CopyIndexes(IndexSet& indexes)
- {
- {
- CReadLock locallock(m_cs);
- indexes = m_indexes;
- }
- return indexes;
- }
- static BOOL IsValidElement(TPTR pElement) {return pElement > E_MAX_STATUS;}
- IndexSet& Indexes () { return m_indexes;}
- DWORD Size () {return m_dwSize;}
- DWORD Elements () {return (DWORD)m_indexes.size();}
- DWORD Spaces () {return m_dwSize - m_dwCount;}
- BOOL HasSpace () {return m_dwCount < m_dwSize;}
- BOOL IsEmpty () {return m_dwCount == 0;}
- BOOL IsValid () {return m_pv != nullptr;}
- private:
- void Create(DWORD dwSize)
- {
- ASSERT(!IsValid() && dwSize > 0);
- m_dwCurSeq = 0;
- m_dwCount = 0;
- m_dwSize = dwSize;
- m_pv = (VTPTR*)malloc(m_dwSize * sizeof(TPTR));
- ::ZeroMemory(m_pv, m_dwSize * sizeof(TPTR));
- }
- void Destroy()
- {
- ASSERT(IsValid());
- m_indexes.clear();
- free((void*)m_pv);
- m_pv = nullptr;
- m_dwSize = 0;
- m_dwCount = 0;
- m_dwCurSeq = 0;
- }
- void EmplaceIndex(index_type dwIndex)
- {
- CWriteLock locallock(m_cs);
- m_indexes.emplace(dwIndex);
- }
- void EraseIndex(index_type dwIndex)
- {
- CWriteLock locallock(m_cs);
- m_indexes.erase(dwIndex);
- }
- public:
- CRingCache (DWORD dwSize = 0)
- : m_pv (nullptr)
- , m_dwSize (0)
- , m_dwCount (0)
- , m_dwCurSeq(0)
- {
- Reset(dwSize);
- }
- ~CRingCache()
- {
- Reset(0);
- }
- private:
- CRingCache(const CRingCache&);
- CRingCache operator = (const CRingCache&);
- private:
- DWORD m_dwSize;
- VTPTR* m_pv;
- char pack1[PACK_SIZE_OF(VTPTR*)];
- volatile DWORD m_dwCurSeq;
- char pack2[PACK_SIZE_OF(DWORD)];
- volatile DWORD m_dwCount;
- char pack3[PACK_SIZE_OF(DWORD)];
- CSimpleRWLock m_cs;
- IndexSet m_indexes;
- };
- template <class T, class index_type, bool adjust_index> T* const CRingCache<T, index_type, adjust_index>::E_EMPTY = (T*)0x00;
- template <class T, class index_type, bool adjust_index> T* const CRingCache<T, index_type, adjust_index>::E_LOCKED = (T*)0x01;
- template <class T, class index_type, bool adjust_index> T* const CRingCache<T, index_type, adjust_index>::E_MAX_STATUS = (T*)0x0F;
- // ------------------------------------------------------------------------------------------------------------- //
- template <class T, class index_type = DWORD, bool adjust_index = false> class CRingCache2
- {
- public:
- enum EnGetResult {GR_FAIL = -1, GR_INVALID = 0, GR_VALID = 1};
- typedef T* TPTR;
- typedef volatile T* VTPTR;
- typedef unordered_set<index_type> IndexSet;
- typedef typename IndexSet::const_iterator IndexSetCI;
- typedef typename IndexSet::iterator IndexSetI;
- static TPTR const E_EMPTY;
- static TPTR const E_LOCKED;
- static TPTR const E_MAX_STATUS;
- static DWORD const MAX_SIZE;
- public:
- static index_type& INDEX_INC(index_type& dwIndex) {if(adjust_index) ++dwIndex; return dwIndex;}
- static index_type& INDEX_DEC(index_type& dwIndex) {if(adjust_index) --dwIndex; return dwIndex;}
- index_type& INDEX_R2V(index_type& dwIndex) {dwIndex += *(m_px + dwIndex) * m_dwSize; return dwIndex;}
- BOOL INDEX_V2R(index_type& dwIndex)
- {
- index_type m = dwIndex % m_dwSize;
- BYTE x = *(m_px + m);
- if(dwIndex / m_dwSize != x)
- return FALSE;
- dwIndex = m;
- return TRUE;
- }
- private:
- VTPTR& INDEX_VAL(index_type dwIndex) {return *(m_pv + dwIndex);}
- public:
- BOOL Put(TPTR pElement, index_type& dwIndex)
- {
- ASSERT(pElement != nullptr);
- if(!IsValid()) return FALSE;
- BOOL isOK = FALSE;
- while(true)
- {
- if(!HasSpace())
- break;
- DWORD dwCurSeq = m_dwCurSeq;
- index_type dwCurIndex = dwCurSeq % m_dwSize;
- VTPTR& pValue = INDEX_VAL(dwCurIndex);
- if(pValue == E_EMPTY)
- {
- if(::InterlockedCompareExchangePointer(&pValue, pElement, E_EMPTY) == E_EMPTY)
- {
- ::InterlockedIncrement(&m_dwCount);
- ::InterlockedCompareExchange(&m_dwCurSeq, dwCurSeq + 1, dwCurSeq);
- dwIndex = INDEX_INC(INDEX_R2V(dwCurIndex));
- isOK = TRUE;
- if(pElement != E_LOCKED)
- EmplaceIndex(dwIndex);
- break;
- }
- }
- ::InterlockedCompareExchange(&m_dwCurSeq, dwCurSeq + 1, dwCurSeq);
- }
- return isOK;
- }
- EnGetResult Get(index_type dwIndex, TPTR* ppElement, index_type* pdwRealIndex = nullptr)
- {
- ASSERT(ppElement != nullptr);
- if(!IsValid() || !INDEX_V2R(INDEX_DEC(dwIndex)))
- {
- *ppElement = nullptr;
- return GR_FAIL;
- }
- *ppElement = (TPTR)INDEX_VAL(dwIndex);
- if(pdwRealIndex) *pdwRealIndex = dwIndex;
- return IsValidElement(*ppElement) ? GR_VALID : GR_INVALID;
- }
- BOOL Set(index_type dwIndex, TPTR pElement, TPTR* ppOldElement = nullptr, index_type* pdwRealIndex = nullptr)
- {
- TPTR pElement2 = nullptr;
- if(pdwRealIndex == nullptr)
- pdwRealIndex = CreateLocalObject(index_type);
- if(Get(dwIndex, &pElement2, pdwRealIndex) == GR_FAIL)
- return FALSE;
- if(ppOldElement != nullptr)
- *ppOldElement = pElement2;
- if(pElement == pElement2)
- return FALSE;
- int f1 = 0;
- int f2 = 0;
- if(pElement == E_EMPTY)
- {
- if(pElement2 == E_LOCKED)
- f1 = -1;
- else
- f1 = f2 = -1;
- }
- else if(pElement == E_LOCKED)
- {
- if(pElement2 == E_EMPTY)
- f1 = 1;
- else
- f2 = -1;
- }
- else
- {
- if(pElement2 == E_EMPTY)
- f1 = f2 = 1;
- else if(pElement2 == E_LOCKED)
- f2 = 1;
- }
- BOOL bSetValueFirst = (f1 + f2 >= 0);
- index_type dwRealIndex = *pdwRealIndex;
- if(bSetValueFirst) INDEX_VAL(dwRealIndex) = pElement;
- if(f1 > 0) ::InterlockedIncrement(&m_dwCount);
- if(f2 != 0) (f2 > 0) ? EmplaceIndex(dwIndex) : EraseIndex(dwIndex);
- if(f1 < 0) {::InterlockedDecrement(&m_dwCount); ++(*(m_px + dwRealIndex));}
- if(!bSetValueFirst) INDEX_VAL(dwRealIndex) = pElement;
- ASSERT(Spaces() <= Size());
- return TRUE;
- }
- BOOL Remove(index_type dwIndex, TPTR* ppElement = nullptr)
- {
- return Set(dwIndex, E_EMPTY, ppElement);
- }
- BOOL AcquireLock(index_type& dwIndex)
- {
- return Put(E_LOCKED, dwIndex);
- }
- BOOL ReleaseLock(index_type dwIndex, TPTR pElement)
- {
- ASSERT(pElement == nullptr || IsValidElement(pElement));
- TPTR pElement2 = nullptr;
- Get(dwIndex, &pElement2);
- ASSERT(pElement2 == E_LOCKED);
- if(pElement2 != E_LOCKED)
- return FALSE;
- return Set(dwIndex, pElement);
- }
- public:
- void Reset(DWORD dwSize = 0)
- {
- if(IsValid())
- Destroy();
- if(dwSize > 0)
- Create(dwSize);
- }
-
- BOOL GetAllElementIndexes(index_type ids[], DWORD& dwCount, BOOL bCopy = TRUE)
- {
- DWORD dwSize = Elements();
- if(ids == nullptr || dwCount == 0)
- {
- dwCount = dwSize;
- return FALSE;
- }
- if(dwSize == 0)
- {
- dwCount = 0;
- return TRUE;
- }
- IndexSet* pIndexes = &m_indexes;
- if(bCopy)
- {
- pIndexes = new IndexSet;
- CopyIndexes(*pIndexes);
- }
- DWORD i = 0;
- for(auto it = pIndexes->begin(), end = pIndexes->end(); i < dwCount && it != end; ++i, ++it)
- ids[i] = *it;
- if(bCopy) delete pIndexes;
- dwCount = i;
- return TRUE;
- }
-
- unique_ptr<index_type[]> GetAllElementIndexes(DWORD& dwCount, BOOL bCopy = TRUE)
- {
- dwCount = (DWORD)m_indexes.size();
- unique_ptr<index_type[]> ids(new index_type[dwCount]);
- if(dwCount > 0)
- GetAllElementIndexes(ids.get(), dwCount, bCopy);
- return ids;
- }
-
- IndexSet& CopyIndexes(IndexSet& indexes)
- {
- {
- CReadLock locallock(m_cs);
- indexes = m_indexes;
- }
- return indexes;
- }
- static BOOL IsValidElement(TPTR pElement) {return pElement > E_MAX_STATUS;}
- IndexSet& Indexes () {return m_indexes;}
- DWORD Size () {return m_dwSize;}
- DWORD Elements () {return (DWORD)m_indexes.size();}
- DWORD Spaces () {return m_dwSize - m_dwCount;}
- BOOL HasSpace () {return m_dwCount < m_dwSize;}
- BOOL IsEmpty () {return m_dwCount == 0;}
- BOOL IsValid () {return m_pv != nullptr;}
- private:
- void Create(DWORD dwSize)
- {
- ASSERT(!IsValid() && dwSize > 0 && dwSize <= MAX_SIZE);
- m_dwCurSeq = 0;
- m_dwCount = 0;
- m_dwSize = dwSize;
- m_pv = (VTPTR*)malloc(m_dwSize * sizeof(TPTR));
- m_px = (BYTE*)malloc(m_dwSize * sizeof(BYTE));
- ::ZeroMemory(m_pv, m_dwSize * sizeof(TPTR));
- ::ZeroMemory(m_px, m_dwSize * sizeof(BYTE));
- }
- void Destroy()
- {
- ASSERT(IsValid());
- m_indexes.clear();
- free((void*)m_pv);
- free((void*)m_px);
- m_pv = nullptr;
- m_px = nullptr;
- m_dwSize = 0;
- m_dwCount = 0;
- m_dwCurSeq = 0;
- }
- void EmplaceIndex(index_type dwIndex)
- {
- CWriteLock locallock(m_cs);
- m_indexes.emplace(dwIndex);
- }
- void EraseIndex(index_type dwIndex)
- {
- CWriteLock locallock(m_cs);
- m_indexes.erase(dwIndex);
- }
- public:
- CRingCache2 (DWORD dwSize = 0)
- : m_pv (nullptr)
- , m_px (nullptr)
- , m_dwSize (0)
- , m_dwCount (0)
- , m_dwCurSeq(0)
- {
- Reset(dwSize);
- }
- ~CRingCache2()
- {
- Reset(0);
- }
- DECLARE_NO_COPY_CLASS(CRingCache2)
- private:
- DWORD m_dwSize;
- VTPTR* m_pv;
- char pack1[PACK_SIZE_OF(VTPTR*)];
- BYTE* m_px;
- char pack2[PACK_SIZE_OF(BYTE*)];
- volatile DWORD m_dwCurSeq;
- char pack3[PACK_SIZE_OF(DWORD)];
- volatile DWORD m_dwCount;
- char pack4[PACK_SIZE_OF(DWORD)];
- CSimpleRWLock m_cs;
- IndexSet m_indexes;
- };
- template <class T, class index_type, bool adjust_index> T* const CRingCache2<T, index_type, adjust_index>::E_EMPTY = (T*)0x00;
- template <class T, class index_type, bool adjust_index> T* const CRingCache2<T, index_type, adjust_index>::E_LOCKED = (T*)0x01;
- template <class T, class index_type, bool adjust_index> T* const CRingCache2<T, index_type, adjust_index>::E_MAX_STATUS = (T*)0x0F;
- template <class T, class index_type, bool adjust_index> DWORD const CRingCache2<T, index_type, adjust_index>::MAX_SIZE =
- #if __WORDSIZE == 32
- 0x00FFFFFF
- #else
- 0xFFFFFFFF
- #endif
- ;
- // ------------------------------------------------------------------------------------------------------------- //
- template <class T> class CRingPool
- {
- private:
- typedef T* TPTR;
- typedef volatile T* VTPTR;
- static TPTR const E_EMPTY;
- static TPTR const E_LOCKED;
- static TPTR const E_MAX_STATUS;
- private:
- VTPTR& INDEX_VAL(DWORD dwIndex) {return *(m_pv + dwIndex);}
- public:
- BOOL TryPut(TPTR pElement)
- {
- ASSERT(pElement != nullptr);
- if(!IsValid()) return FALSE;
- BOOL isOK = FALSE;
- for(DWORD i = 0; i < m_dwSize; i++)
- {
- DWORD seqPut = m_seqPut;
- if(!HasPutSpace(seqPut))
- break;
- DWORD dwIndex = seqPut % m_dwSize;
- VTPTR& pValue = INDEX_VAL(dwIndex);
- TPTR pCurrent = (TPTR)pValue;
- if(pCurrent == E_EMPTY)
- {
- if(::InterlockedCompareExchangePointer(&pValue, pElement, pCurrent) == pCurrent)
- {
- ::InterlockedCompareExchange(&m_seqPut, seqPut + 1, seqPut);
- isOK = TRUE;
- break;
- }
- }
- ::InterlockedCompareExchange(&m_seqPut, seqPut + 1, seqPut);
- }
- return isOK;
- }
- BOOL TryGet(TPTR* ppElement)
- {
- ASSERT(ppElement != nullptr);
- if(!IsValid()) return FALSE;
- BOOL isOK = FALSE;
- while(true)
- {
- DWORD seqGet = m_seqGet;
- if(!HasGetSpace(seqGet))
- break;
- DWORD dwIndex = seqGet % m_dwSize;
- VTPTR& pValue = INDEX_VAL(dwIndex);
- TPTR pCurrent = (TPTR)pValue;
- if(pCurrent > E_MAX_STATUS)
- {
- if(::InterlockedCompareExchangePointer(&pValue, E_EMPTY, pCurrent) == pCurrent)
- {
- ::InterlockedCompareExchange(&m_seqGet, seqGet + 1, seqGet);
- *(ppElement) = pCurrent;
- isOK = TRUE;
- break;
- }
- }
- ::InterlockedCompareExchange(&m_seqGet, seqGet + 1, seqGet);
- }
- return isOK;
- }
- BOOL TryLock(TPTR* ppElement, DWORD& dwIndex)
- {
- ASSERT(ppElement != nullptr);
- if(!IsValid()) return FALSE;
- BOOL isOK = FALSE;
- while(true)
- {
- DWORD seqGet = m_seqGet;
- if(!HasGetSpace(seqGet))
- break;
- dwIndex = seqGet % m_dwSize;
- VTPTR& pValue = INDEX_VAL(dwIndex);
- TPTR pCurrent = (TPTR)pValue;
- if(pCurrent > E_MAX_STATUS)
- {
- if(::InterlockedCompareExchangePointer(&pValue, E_LOCKED, pCurrent) == pCurrent)
- {
- ::InterlockedCompareExchange(&m_seqGet, seqGet + 1, seqGet);
- *(ppElement) = pCurrent;
- isOK = TRUE;
- break;
- }
- }
- ::InterlockedCompareExchange(&m_seqGet, seqGet + 1, seqGet);
- }
- return isOK;
- }
- BOOL ReleaseLock(TPTR pElement, DWORD dwIndex)
- {
- ASSERT(dwIndex < m_dwSize);
- ASSERT(pElement == nullptr || pElement > E_MAX_STATUS);
- if(!IsValid()) return FALSE;
- VTPTR& pValue = INDEX_VAL(dwIndex);
- ENSURE(pValue == E_LOCKED);
- if(pElement == nullptr)
- pValue = E_EMPTY;
- else
- pValue = pElement;
- return TRUE;
- }
- public:
- void Reset(DWORD dwSize = 0)
- {
- if(IsValid())
- Destroy();
- if(dwSize > 0)
- Create(dwSize);
- }
- void Clear()
- {
- for(DWORD dwIndex = 0; dwIndex < m_dwSize; dwIndex++)
- {
- VTPTR& pValue = INDEX_VAL(dwIndex);
- if(pValue > E_MAX_STATUS)
- {
- T::Destruct((TPTR)pValue);
- pValue = E_EMPTY;
- }
- }
- Reset();
- }
- DWORD Size() {return m_dwSize;}
- DWORD Elements() {return m_seqPut - m_seqGet;}
- BOOL IsFull() {return Elements() == Size();}
- BOOL IsEmpty() {return Elements() == 0;}
- BOOL IsValid() {return m_pv != nullptr;}
- private:
- BOOL HasPutSpace(DWORD seqPut)
- {
- return ((int)(seqPut - m_seqGet) < (int)m_dwSize);
- }
- BOOL HasGetSpace(DWORD seqGet)
- {
- return ((int)(m_seqPut - seqGet) > 0);
- }
- void Create(DWORD dwSize)
- {
- ASSERT(!IsValid() && dwSize > 0);
- m_seqPut = 0;
- m_seqGet = 0;
- m_dwSize = dwSize;
- m_pv = (VTPTR*)malloc(m_dwSize * sizeof(TPTR));
- ::ZeroMemory(m_pv, m_dwSize * sizeof(TPTR));
- }
- void Destroy()
- {
- ASSERT(IsValid());
- free((void*)m_pv);
- m_pv = nullptr;
- m_dwSize = 0;
- m_seqPut = 0;
- m_seqGet = 0;
- }
- public:
- CRingPool(DWORD dwSize = 0)
- : m_pv(nullptr)
- , m_dwSize(0)
- , m_seqPut(0)
- , m_seqGet(0)
- {
- Reset(dwSize);
- }
- ~CRingPool()
- {
- Reset(0);
- }
- private:
- CRingPool(const CRingPool&);
- CRingPool operator = (const CRingPool&);
- private:
- DWORD m_dwSize;
- VTPTR* m_pv;
- char pack1[PACK_SIZE_OF(VTPTR*)];
- volatile DWORD m_seqPut;
- char pack2[PACK_SIZE_OF(DWORD)];
- volatile DWORD m_seqGet;
- char pack3[PACK_SIZE_OF(DWORD)];
- };
- template <class T> T* const CRingPool<T>::E_EMPTY = (T*)0x00;
- template <class T> T* const CRingPool<T>::E_LOCKED = (T*)0x01;
- template <class T> T* const CRingPool<T>::E_MAX_STATUS = (T*)0x0F;
- // ------------------------------------------------------------------------------------------------------------- //
- template <class T> class CCASQueueX
- {
- private:
- struct Node;
- typedef Node* NPTR;
- typedef volatile Node* VNPTR;
- typedef volatile UINT VUINT;
- struct Node
- {
- T* pValue;
- VNPTR pNext;
- Node(T* val, NPTR next = nullptr)
- : pValue(val), pNext(next)
- {
- }
- };
- public:
- void PushBack(T* pVal)
- {
- ASSERT(pVal != nullptr);
- VNPTR pTail = nullptr;
- NPTR pNode = new Node(pVal);
- while(true)
- {
- pTail = m_pTail;
- if(::InterlockedCompareExchangePointer(&m_pTail, pNode, pTail) == pTail)
- {
- pTail->pNext = pNode;
- break;
- }
- }
- ::InterlockedIncrement(&m_iSize);
- }
- void UnsafePushBack(T* pVal)
- {
- ASSERT(pVal != nullptr);
- NPTR pNode = new Node(pVal);
- m_pTail->pNext = pNode;
- m_pTail = pNode;
-
- ::InterlockedIncrement(&m_iSize);
- }
- BOOL PopFront(T** ppVal)
- {
- ASSERT(ppVal != nullptr);
- if(IsEmpty())
- return FALSE;
- BOOL isOK = FALSE;
- NPTR pHead = nullptr;
- NPTR pNext = nullptr;
- while(true)
- {
- Lock();
- pHead = (NPTR)m_pHead;
- pNext = (NPTR)pHead->pNext;
- if(pNext == nullptr)
- {
- Unlock();
- break;
- }
- *ppVal = pNext->pValue;
- m_pHead = pNext;
- Unlock();
- isOK = TRUE;
- ::InterlockedDecrement(&m_iSize);
- delete pHead;
- break;
- }
- return isOK;
- }
- BOOL UnsafePopFront(T** ppVal)
- {
- if(!UnsafePeekFront(ppVal))
- return FALSE;
- UnsafePopFrontNotCheck();
- return TRUE;
- }
- BOOL UnsafePeekFront(T** ppVal)
- {
- ASSERT(ppVal != nullptr);
- NPTR pNext = (NPTR)m_pHead->pNext;
- if(pNext == nullptr)
- return FALSE;
- *ppVal = pNext->pValue;
- return TRUE;
- }
- void UnsafePopFrontNotCheck()
- {
- NPTR pHead = (NPTR)m_pHead;
- NPTR pNext = (NPTR)pHead->pNext;
- m_pHead = pNext;
- ::InterlockedDecrement(&m_iSize);
- delete pHead;
- }
- void UnsafeClear()
- {
- ASSERT(m_pHead != nullptr);
- m_dwCheckTime = 0;
- while(m_pHead->pNext != nullptr)
- UnsafePopFrontNotCheck();
- }
- public:
- UINT Size() {return m_iSize;}
- BOOL IsEmpty() {return m_iSize == 0;}
- void Lock() {while(!TryLock()) ::YieldProcessor();}
- void Unlock() {m_iLock = 0;}
- BOOL TryLock() {return (::InterlockedCompareExchange(&m_iLock, 1u, 0u) == 0);}
- DWORD GetCheckTime()
- {
- return m_dwCheckTime;
- }
- void UpdateCheckTime(DWORD dwCurrent = 0)
- {
- if(dwCurrent == 0)
- dwCurrent = ::TimeGetTime();
- m_dwCheckTime = dwCurrent;
- }
- int GetCheckTimeGap(DWORD dwCurrent = 0)
- {
- int rs = (int)GetTimeGap32(m_dwCheckTime, dwCurrent);
- if(rs < -60 * 1000)
- rs = MAXINT;
- return rs;
- }
- public:
- CCASQueueX() : m_iLock(0), m_iSize(0), m_dwCheckTime(0)
- {
- m_pHead = m_pTail = new Node(nullptr);
- }
- ~CCASQueueX()
- {
- ASSERT(m_iLock == 0);
- ASSERT(m_iSize == 0);
- ASSERT(m_pTail == m_pHead);
- ASSERT(m_pHead != nullptr);
- ASSERT(m_pHead->pNext == nullptr);
- UnsafeClear();
- delete m_pHead;
- }
- DECLARE_NO_COPY_CLASS(CCASQueueX)
- private:
- VUINT m_iLock;
- VUINT m_iSize;
- VNPTR m_pHead;
- VNPTR m_pTail;
- volatile DWORD m_dwCheckTime;
- };
- template <class T> class CCASSimpleQueueX
- {
- private:
- struct Node;
- typedef Node* NPTR;
- typedef volatile Node* VNPTR;
- typedef volatile UINT VUINT;
- struct Node
- {
- T tValue;
- VNPTR pNext;
- Node(T val, NPTR next = nullptr)
- : tValue(val), pNext(next)
- {
- }
- };
- public:
- void PushBack(T tVal)
- {
- VNPTR pTail = nullptr;
- NPTR pNode = new Node(tVal);
- while(true)
- {
- pTail = m_pTail;
- if(::InterlockedCompareExchangePointer(&m_pTail, pNode, pTail) == pTail)
- {
- pTail->pNext = pNode;
- break;
- }
- }
- ::InterlockedIncrement(&m_iSize);
- }
- void UnsafePushBack(T tVal)
- {
- NPTR pNode = new Node(tVal);
- m_pTail->pNext = pNode;
- m_pTail = pNode;
-
- ::InterlockedIncrement(&m_iSize);
- }
- BOOL PopFront(T* ptVal)
- {
- ASSERT(ptVal != nullptr);
- if(IsEmpty())
- return FALSE;
- BOOL isOK = FALSE;
- NPTR pHead = nullptr;
- NPTR pNext = nullptr;
- while(true)
- {
- Lock();
- pHead = (NPTR)m_pHead;
- pNext = (NPTR)pHead->pNext;
- if(pNext == nullptr)
- {
- Unlock();
- break;
- }
- *ptVal = pNext->tValue;
- m_pHead = pNext;
- Unlock();
- isOK = TRUE;
- ::InterlockedDecrement(&m_iSize);
- delete pHead;
- break;
- }
- return isOK;
- }
- BOOL UnsafePopFront(T* ptVal)
- {
- if(!UnsafePeekFront(ptVal))
- return FALSE;
- UnsafePopFrontNotCheck();
- return TRUE;
- }
- BOOL UnsafePeekFront(T* ptVal)
- {
- ASSERT(ptVal != nullptr);
- NPTR pNext = (NPTR)m_pHead->pNext;
- if(pNext == nullptr)
- return FALSE;
- *ptVal = pNext->pValue;
- return TRUE;
- }
- void UnsafePopFrontNotCheck()
- {
- NPTR pHead = (NPTR)m_pHead;
- NPTR pNext = (NPTR)pHead->pNext;
- m_pHead = pNext;
- ::InterlockedDecrement(&m_iSize);
- delete pHead;
- }
- void UnsafeClear()
- {
- ASSERT(m_pHead != nullptr);
- m_dwCheckTime = 0;
- while(m_pHead->pNext != nullptr)
- UnsafePopFrontNotCheck();
- }
- public:
- UINT Size() {return m_iSize;}
- BOOL IsEmpty() {return m_iSize == 0;}
- void Lock() {while(!TryLock()) ::YieldProcessor();}
- void Unlock() {m_iLock = 0;}
- BOOL TryLock() {return (::InterlockedCompareExchange(&m_iLock, 1u, 0u) == 0);}
- DWORD GetCheckTime()
- {
- return m_dwCheckTime;
- }
- void UpdateCheckTime(DWORD dwCurrent = 0)
- {
- if(dwCurrent == 0)
- dwCurrent = ::TimeGetTime();
- m_dwCheckTime = dwCurrent;
- }
- int GetCheckTimeGap(DWORD dwCurrent = 0)
- {
- int rs = (int)GetTimeGap32(m_dwCheckTime, dwCurrent);
- if(rs < -60 * 1000)
- rs = MAXINT;
- return rs;
- }
- public:
- CCASSimpleQueueX() : m_iLock(0), m_iSize(0), m_dwCheckTime(0)
- {
- m_pHead = m_pTail = new Node(0);
- }
- ~CCASSimpleQueueX()
- {
- ASSERT(m_iLock == 0);
- ASSERT(m_iSize == 0);
- ASSERT(m_pTail == m_pHead);
- ASSERT(m_pHead != nullptr);
- ASSERT(m_pHead->pNext == nullptr);
- UnsafeClear();
- delete m_pHead;
- }
- DECLARE_NO_COPY_CLASS(CCASSimpleQueueX)
- private:
- VUINT m_iLock;
- VUINT m_iSize;
- VNPTR m_pHead;
- VNPTR m_pTail;
- volatile DWORD m_dwCheckTime;
- };
- template <class T> class CCASQueueY
- {
- public:
- void PushBack(T* pVal)
- {
- CCriSecLock locallock(m_csGuard);
- UnsafePushBack(pVal);
- }
- void UnsafePushBack(T* pVal)
- {
- ASSERT(pVal != nullptr);
- m_lsItems.push_back(pVal);
- }
- void PushFront(T* pVal)
- {
- CCriSecLock locallock(m_csGuard);
- UnsafePushFront(pVal);
- }
- void UnsafePushFront(T* pVal)
- {
- ASSERT(pVal != nullptr);
- m_lsItems.push_front(pVal);
- }
- BOOL PopFront(T** ppVal)
- {
- CCriSecLock locallock(m_csGuard);
- return UnsafePopFront(ppVal);
- }
- BOOL UnsafePopFront(T** ppVal)
- {
- if(!UnsafePeekFront(ppVal))
- return FALSE;
- UnsafePopFrontNotCheck();
- return TRUE;
- }
- BOOL PeekFront(T** ppVal)
- {
- CCriSecLock locallock(m_csGuard);
- return UnsafePeekFront(ppVal);
- }
- BOOL UnsafePeekFront(T** ppVal)
- {
- ASSERT(ppVal != nullptr);
- if(m_lsItems.empty())
- return FALSE;
- *ppVal = m_lsItems.front();
- return TRUE;
- }
- void UnsafePopFrontNotCheck()
- {
- m_lsItems.pop_front();
- }
- void Clear()
- {
- CCriSecLock locallock(m_csGuard);
- UnsafeClear();
- }
- void UnsafeClear()
- {
- m_dwCheckTime = 0;
- m_lsItems.clear();
- }
- public:
- ULONG Size() {return (ULONG)m_lsItems.size();}
- BOOL IsEmpty() {return (BOOL)m_lsItems.empty();}
- void Lock() {m_csGuard.lock();}
- void Unlock() {m_csGuard.unlock();}
- BOOL TryLock() {return m_csGuard.try_lock();}
- CCriSec& Guard(){return m_csGuard;}
- DWORD GetCheckTime()
- {
- return m_dwCheckTime;
- }
- void UpdateCheckTime(DWORD dwCurrent = 0)
- {
- if(dwCurrent == 0)
- dwCurrent = ::TimeGetTime();
- m_dwCheckTime = dwCurrent;
- }
- int GetCheckTimeGap(DWORD dwCurrent = 0)
- {
- int rs = (int)GetTimeGap32(m_dwCheckTime, dwCurrent);
- if(rs < -60 * 1000)
- rs = MAXINT;
- return rs;
- }
- public:
- CCASQueueY()
- : m_dwCheckTime(0)
- {
- }
- ~CCASQueueY()
- {
- ASSERT(IsEmpty());
- UnsafeClear();
- }
- DECLARE_NO_COPY_CLASS(CCASQueueY)
- private:
- CCriSec m_csGuard;
- deque<T*> m_lsItems;
-
- volatile DWORD m_dwCheckTime;
- };
- template <class T> class CCASSimpleQueueY
- {
- public:
- void PushBack(T tVal)
- {
- CCriSecLock locallock(m_csGuard);
- UnsafePushBack(tVal);
- }
- void UnsafePushBack(T tVal)
- {
- m_lsItems.push_back(tVal);
- }
- void PushFront(T tVal)
- {
- CCriSecLock locallock(m_csGuard);
- UnsafePushFront(tVal);
- }
- void UnsafePushFront(T tVal)
- {
- m_lsItems.push_front(tVal);
- }
- BOOL PopFront(T* ptVal)
- {
- CCriSecLock locallock(m_csGuard);
- return UnsafePopFront(ptVal);
- }
- BOOL UnsafePopFront(T* ptVal)
- {
- if(!UnsafePeekFront(ptVal))
- return FALSE;
- UnsafePopFrontNotCheck();
- return TRUE;
- }
- BOOL PeekFront(T* ptVal)
- {
- CCriSecLock locallock(m_csGuard);
- return UnsafePeekFront(ptVal);
- }
- BOOL UnsafePeekFront(T* ptVal)
- {
- ASSERT(ptVal != nullptr);
- if(m_lsItems.empty())
- return FALSE;
- *ptVal = m_lsItems.front();
- return TRUE;
- }
- void UnsafePopFrontNotCheck()
- {
- m_lsItems.pop_front();
- }
- void Clear()
- {
- CCriSecLock locallock(m_csGuard);
- UnsafeClear();
- }
- void UnsafeClear()
- {
- m_dwCheckTime = 0;
- m_lsItems.clear();
- }
- public:
- ULONG Size() {return (ULONG)m_lsItems.size();}
- BOOL IsEmpty() {return (BOOL)m_lsItems.empty();}
- void Lock() {m_csGuard.lock();}
- void Unlock() {m_csGuard.unlock();}
- BOOL TryLock() {return m_csGuard.try_lock();}
- CCriSec& Guard(){return m_csGuard;}
- DWORD GetCheckTime()
- {
- return m_dwCheckTime;
- }
- void UpdateCheckTime(DWORD dwCurrent = 0)
- {
- if(dwCurrent == 0)
- dwCurrent = ::TimeGetTime();
- m_dwCheckTime = dwCurrent;
- }
- int GetCheckTimeGap(DWORD dwCurrent = 0)
- {
- int rs = (int)GetTimeGap32(m_dwCheckTime, dwCurrent);
- if(rs < -60 * 1000)
- rs = MAXINT;
- return rs;
- }
- public:
- CCASSimpleQueueY()
- : m_dwCheckTime(0)
- {
- }
- ~CCASSimpleQueueY()
- {
- ASSERT(IsEmpty());
- UnsafeClear();
- }
- DECLARE_NO_COPY_CLASS(CCASSimpleQueueY)
- private:
- CCriSec m_csGuard;
- deque<T> m_lsItems;
-
- volatile DWORD m_dwCheckTime;
- };
- template <class T> using CCASQueue = CCASQueueX<T>;
- template <class T> using CCASSimpleQueue = CCASSimpleQueueX<T>;
- template<typename T>
- void ReleaseGCObj(CCASQueue<T>& lsGC, DWORD dwLockTime, BOOL bForce = FALSE)
- {
- static const int MIN_CHECK_INTERVAL = 1 * 1000;
- static const int MAX_CHECK_INTERVAL = 15 * 1000;
- T* pObj = nullptr;
- if(bForce)
- {
- CLocalLock<CCASQueue<T>> locallock(lsGC);
- while(lsGC.UnsafePeekFront(&pObj))
- {
- lsGC.UnsafePopFrontNotCheck();
- T::Destruct(pObj);
- }
- }
- else
- {
- if(lsGC.IsEmpty() || lsGC.GetCheckTimeGap() < MAX(MIN((int)(dwLockTime / 3), MAX_CHECK_INTERVAL), MIN_CHECK_INTERVAL))
- return;
- T* pFirst = nullptr;
- BOOL bFirst = TRUE;
- DWORD now = 0;
- while(TRUE)
- {
- ASSERT((pObj = nullptr) == nullptr);
- {
- CLocalTryLock<CCASQueue<T>> locallock(lsGC);
- if(!locallock.IsValid())
- break;
- if(bFirst)
- {
- bFirst = FALSE;
- now = ::TimeGetTime();
- lsGC.UpdateCheckTime(now);
- }
- if(!lsGC.UnsafePeekFront(&pObj))
- break;
- if((int)(now - pObj->GetFreeTime()) < (int)dwLockTime)
- break;
- lsGC.UnsafePopFrontNotCheck();
- if(pObj->GetCount() > 0)
- {
- lsGC.PushBack(pObj);
- if(pFirst == nullptr)
- pFirst = pObj;
- else if(pFirst == pObj)
- break;
- continue;
- }
- }
- ASSERT(pObj != nullptr);
- T::Destruct(pObj);
- }
- }
- }
- #if __WORDSIZE == 32
- #pragma pack(pop)
- #endif
|