| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- /*
- * 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 "FuncHelper.h"
- #include <mutex>
- #include <atomic>
- using namespace std;
- class CSpinGuard
- {
- public:
- CSpinGuard() : m_atFlag(FALSE)
- {
- }
- ~CSpinGuard()
- {
- ASSERT(!m_atFlag);
- }
- void Lock(BOOL bWeek = TRUE, memory_order m = memory_order_acquire)
- {
- for(UINT i = 0; !TryLock(bWeek, m); ++i)
- YieldThread(i);
- }
- BOOL TryLock(BOOL bWeek = FALSE, memory_order m = memory_order_acquire)
- {
- BOOL bExpect = FALSE;
- return bWeek
- ? m_atFlag.compare_exchange_weak(bExpect, TRUE, m)
- : m_atFlag.compare_exchange_strong(bExpect, TRUE, m);
- }
- void Unlock(memory_order m = memory_order_release)
- {
- ASSERT(m_atFlag);
- m_atFlag.store(FALSE, m);
- }
- DECLARE_NO_COPY_CLASS(CSpinGuard)
- private:
- atomic<BOOL> m_atFlag;
- };
- class CReentrantSpinGuard
- {
- public:
- CReentrantSpinGuard()
- : m_atThreadID (0)
- , m_iCount (0)
- {
- }
- ~CReentrantSpinGuard()
- {
- ASSERT(m_atThreadID == 0);
- ASSERT(m_iCount == 0);
- }
- void Lock(BOOL bWeek = TRUE, memory_order m = memory_order_acquire)
- {
- for(UINT i = 0; !_TryLock(i == 0, bWeek, m); ++i)
- YieldThread(i);
- }
- BOOL TryLock(BOOL bWeek = FALSE, memory_order m = memory_order_acquire)
- {
- return _TryLock(TRUE, bWeek, m);
- }
- void Unlock(memory_order m = memory_order_release)
- {
- ASSERT(::IsSelfThread(m_atThreadID));
- if((--m_iCount) == 0)
- m_atThreadID.store(0, m);
- }
- private:
- BOOL _TryLock(BOOL bFirst, BOOL bWeek = FALSE, memory_order m = memory_order_acquire)
- {
- THR_ID dwCurrentThreadID = SELF_THREAD_ID;
- if(bFirst && ::IsSameThread(m_atThreadID, dwCurrentThreadID))
- {
- ++m_iCount;
- return TRUE;
- }
- THR_ID ulExpect = 0;
- BOOL isOK = bWeek
- ? m_atThreadID.compare_exchange_weak(ulExpect, dwCurrentThreadID, m)
- : m_atThreadID.compare_exchange_strong(ulExpect, dwCurrentThreadID, m);
- if(isOK)
- {
- ASSERT(m_iCount == 0);
- m_iCount = 1;
- return TRUE;
- }
- return FALSE;
- }
- DECLARE_NO_COPY_CLASS(CReentrantSpinGuard)
- private:
- atomic_tid m_atThreadID;
- int m_iCount;
- };
- class CFakeGuard
- {
- public:
- void Lock() {}
- void Unlock() {}
- BOOL TryLock() {return TRUE;}
- };
- template<class CLockObj> class CLocalLock
- {
- public:
- CLocalLock(CLockObj& obj) : m_lock(obj) {m_lock.Lock();}
- ~CLocalLock() {m_lock.Unlock();}
- private:
- CLockObj& m_lock;
- };
- template<class CLockObj> class CLocalTryLock
- {
- public:
- CLocalTryLock(CLockObj& obj) : m_lock(obj) {m_bValid = m_lock.TryLock();}
- ~CLocalTryLock() {if(m_bValid) m_lock.Unlock();}
- BOOL IsValid() {return m_bValid;}
- private:
- CLockObj& m_lock;
- BOOL m_bValid;
- };
- template<class CMTXObj> class CMTXTryLock
- {
- public:
- CMTXTryLock(CMTXObj& obj) : m_lock(obj) {m_bValid = m_lock.try_lock();}
- ~CMTXTryLock() {if(m_bValid) m_lock.unlock();}
- BOOL IsValid() {return m_bValid;}
- private:
- CMTXObj& m_lock;
- BOOL m_bValid;
- };
- using CSpinLock = CLocalLock<CSpinGuard>;
- using CReentrantSpinLock = CLocalLock<CReentrantSpinGuard>;
- using CFakeLock = CLocalLock<CFakeGuard>;
- using CCriSec = mutex;
- using CCriSecLock = lock_guard<mutex>;
- using CCriSecLock2 = unique_lock<mutex>;
- using CCriSecTryLock = CMTXTryLock<mutex>;
- using CMTX = CCriSec;
- using CMutexLock = CCriSecLock;
- using CMutexLock2 = CCriSecLock2;
- using CMutexTryLock = CCriSecTryLock;
- using CReentrantCriSec = recursive_mutex;
- using CReentrantCriSecLock = lock_guard<recursive_mutex>;
- using CReentrantCriSecLock2 = unique_lock<recursive_mutex>;
- using CReentrantCriSecTryLock = CMTXTryLock<recursive_mutex>;
- using CReentrantMTX = CReentrantCriSec;
- using CReentrantMutexLock = CReentrantCriSecLock;
- using CReentrantMutexLock2 = CReentrantCriSecLock2;
- using CReentrantMutexTryLock = CReentrantCriSecTryLock;
- template<typename T, typename = enable_if_t<is_arithmetic<T>::value>> class CSafeCounterT
- {
- public:
- T Increment() {return ::InterlockedIncrement(&m_iCount);}
- T Decrement() {return ::InterlockedDecrement(&m_iCount);}
- T AddFetch(T iCount) {return ::InterlockedAdd(&m_iCount, iCount);}
- T SubFetch(T iCount) {return ::InterlockedSub(&m_iCount, iCount);}
- T FetchAdd(T iCount) {return ::InterlockedExchangeAdd(&m_iCount, iCount);}
- T FetchSub(T iCount) {return ::InterlockedExchangeSub(&m_iCount, iCount);}
- T SetCount(T iCount) {return (m_iCount = iCount);}
- T ResetCount() {return SetCount(0);}
- T GetCount() {return m_iCount;}
- T operator ++ () {return Increment();}
- T operator -- () {return Decrement();}
- T operator ++ (int) {return FetchAdd(1);}
- T operator -- (int) {return FetchSub(1);}
- T operator += (T iCount) {return AddFetch(iCount);}
- T operator -= (T iCount) {return SubFetch(iCount);}
- T operator = (T iCount) {return SetCount(iCount);}
- operator T () {return GetCount();}
- public:
- CSafeCounterT(T iCount = 0) : m_iCount(iCount) {}
- protected:
- volatile T m_iCount;
- };
- template<typename T, typename = enable_if_t<is_arithmetic<T>::value>> class CUnsafeCounterT
- {
- public:
- T Increment() {return ++m_iCount;}
- T Decrement() {return --m_iCount;}
- T AddFetch(T iCount) {return m_iCount += iCount;}
- T SubFetch(T iCount) {return m_iCount -= iCount;}
- T FetchAdd(T iCount) {T rs = m_iCount; m_iCount += iCount; return rs;}
- T FetchSub(T iCount) {T rs = m_iCount; m_iCount -= iCount; return rs;}
- T SetCount(T iCount) {return (m_iCount = iCount);}
- T ResetCount() {return SetCount(0);}
- T GetCount() {return m_iCount;}
- T operator ++ () {return Increment();}
- T operator -- () {return Decrement();}
- T operator ++ (int) {return FetchAdd(1);}
- T operator -- (int) {return FetchSub(1);}
- T operator += (T iCount) {return AddFetch(iCount);}
- T operator -= (T iCount) {return SubFetch(iCount);}
- T operator = (T iCount) {return SetCount(iCount);}
- operator T () {return GetCount();}
- public:
- CUnsafeCounterT(T iCount = 0) : m_iCount(iCount) {}
- protected:
- T m_iCount;
- };
- template<class CCounter> class CLocalCounter
- {
- public:
- CLocalCounter(CCounter& obj) : m_counter(obj) {m_counter.Increment();}
- ~CLocalCounter() {m_counter.Decrement();}
- private:
- CCounter& m_counter;
- };
- using CSafeCounter = CSafeCounterT<INT>;
- using CSafeBigCounter = CSafeCounterT<LONGLONG>;
- using CUnsafeCounter = CUnsafeCounterT<INT>;
- using CUnsafeBigCounter = CUnsafeCounterT<LONGLONG>;
- using CLocalSafeCounter = CLocalCounter<CSafeCounter>;
- using CLocalSafeBigCounter = CLocalCounter<CSafeBigCounter>;
- using CLocalUnsafeCounter = CLocalCounter<CUnsafeCounter>;
- using CLocalUnsafeBigCounter = CLocalCounter<CUnsafeBigCounter>;
|