RWLock.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. /*
  2. * Copyright: JessMA Open Source (ldcsaa@gmail.com)
  3. *
  4. * Version : 2.3.15
  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
  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 "CriticalSection.h"
  26. #include "Semaphore.h"
  27. class CSWMR
  28. {
  29. public:
  30. VOID WaitToRead();
  31. VOID WaitToWrite();
  32. VOID ReadDone() {Done();}
  33. VOID WriteDone() {Done();}
  34. private:
  35. VOID Done();
  36. public:
  37. CSWMR();
  38. ~CSWMR();
  39. private:
  40. CSWMR(const CSWMR&);
  41. CSWMR operator = (const CSWMR&);
  42. private:
  43. int m_nWaitingReaders;
  44. int m_nWaitingWriters;
  45. int m_nActive;
  46. CSpinGuard m_cs;
  47. CSEM m_smRead;
  48. CSEM m_smWrite;
  49. };
  50. #if _WIN32_WINNT >= _WIN32_WINNT_WS08
  51. class CSlimLock
  52. {
  53. public:
  54. VOID WaitToRead() {::AcquireSRWLockShared(&m_lock);}
  55. VOID WaitToWrite() {::AcquireSRWLockExclusive(&m_lock);}
  56. VOID ReadDone() {::ReleaseSRWLockShared(&m_lock);}
  57. VOID WriteDone() {::ReleaseSRWLockExclusive(&m_lock);}
  58. BOOL TryWaitToRead() {return ::TryAcquireSRWLockShared(&m_lock);}
  59. BOOL TryWaitToWrite() {return ::TryAcquireSRWLockExclusive(&m_lock);}
  60. SRWLOCK* GetObject() {return &m_lock;}
  61. public:
  62. CSlimLock() {::InitializeSRWLock(&m_lock);}
  63. ~CSlimLock() {}
  64. private:
  65. CSlimLock(const CSlimLock&);
  66. CSlimLock operator = (const CSlimLock&);
  67. private:
  68. SRWLOCK m_lock;
  69. };
  70. class CSlimRWLock
  71. {
  72. public:
  73. VOID WaitToRead();
  74. VOID WaitToWrite();
  75. VOID ReadDone();
  76. VOID WriteDone();
  77. private:
  78. BOOL IsOwner() {return m_dwWriterTID == ::GetCurrentThreadId();}
  79. VOID SetOwner() {m_dwWriterTID = ::GetCurrentThreadId();}
  80. VOID DetachOwner() {m_dwWriterTID = 0;}
  81. public:
  82. CSlimRWLock();
  83. ~CSlimRWLock();
  84. private:
  85. CSlimRWLock(const CSlimRWLock&);
  86. CSlimRWLock operator = (const CSlimRWLock&);
  87. private:
  88. int m_nActive;
  89. int m_nReadCount;
  90. DWORD m_dwWriterTID;
  91. CSpinGuard m_cs;
  92. CSlimLock m_smLock;
  93. };
  94. #endif
  95. class CSEMRWLock
  96. {
  97. public:
  98. VOID WaitToRead();
  99. VOID WaitToWrite();
  100. VOID ReadDone();
  101. VOID WriteDone();
  102. private:
  103. VOID Done (CSEM** ppSem, LONG& lCount);
  104. BOOL IsOwner() {return m_dwWriterTID == ::GetCurrentThreadId();}
  105. VOID SetOwner() {m_dwWriterTID = ::GetCurrentThreadId();}
  106. VOID DetachOwner() {m_dwWriterTID = 0;}
  107. public:
  108. CSEMRWLock();
  109. ~CSEMRWLock();
  110. private:
  111. CSEMRWLock(const CSEMRWLock&);
  112. CSEMRWLock operator = (const CSEMRWLock&);
  113. private:
  114. int m_nWaitingReaders;
  115. int m_nWaitingWriters;
  116. int m_nActive;
  117. DWORD m_dwWriterTID;
  118. CSpinGuard m_cs;
  119. CSEM m_smRead;
  120. CSEM m_smWrite;
  121. };
  122. template<class CLockObj> class CLocalReadLock
  123. {
  124. public:
  125. CLocalReadLock(CLockObj& obj) : m_wait(obj) {m_wait.WaitToRead();}
  126. ~CLocalReadLock() {m_wait.ReadDone();}
  127. private:
  128. CLocalReadLock(const CLocalReadLock&);
  129. CLocalReadLock operator = (const CLocalReadLock&);
  130. private:
  131. CLockObj& m_wait;
  132. };
  133. template<class CLockObj> class CLocalWriteLock
  134. {
  135. public:
  136. CLocalWriteLock(CLockObj& obj) : m_wait(obj) {m_wait.WaitToWrite();}
  137. ~CLocalWriteLock() {m_wait.WriteDone();}
  138. private:
  139. CLocalWriteLock(const CLocalWriteLock&);
  140. CLocalWriteLock operator = (const CLocalWriteLock&);
  141. private:
  142. CLockObj& m_wait;
  143. };
  144. #if _WIN32_WINNT >= _WIN32_WINNT_WS08
  145. typedef CSlimLock CSimpleRWLock;
  146. #else
  147. typedef CSWMR CSimpleRWLock;
  148. #endif
  149. typedef CLocalReadLock<CSimpleRWLock> CReadLock;
  150. typedef CLocalWriteLock<CSimpleRWLock> CWriteLock;
  151. typedef CSEMRWLock CRWLock;
  152. typedef CLocalReadLock<CRWLock> CReentrantReadLock;
  153. typedef CLocalWriteLock<CRWLock> CReentrantWriteLock;
  154. #if _WIN32_WINNT >= _WIN32_WINNT_WS08
  155. class ICVCondition
  156. {
  157. public:
  158. virtual BOOL Detect() = 0;
  159. public:
  160. virtual ~ICVCondition() {}
  161. };
  162. class CCVCriSec
  163. {
  164. public:
  165. CCVCriSec(CInterCriSec& cs)
  166. : m_cs(cs)
  167. {
  168. ::InitializeConditionVariable(&m_cv);
  169. }
  170. ~CCVCriSec() {}
  171. void WaitToRead(ICVCondition* pCondition)
  172. {
  173. Wait(pCondition);
  174. }
  175. void WaitToWrite(ICVCondition* pCondition)
  176. {
  177. Wait(pCondition);
  178. }
  179. void ReadDone()
  180. {
  181. Done();
  182. }
  183. void WriteDone()
  184. {
  185. Done();
  186. }
  187. void WakeUp()
  188. {
  189. ::WakeConditionVariable(&m_cv);
  190. }
  191. void WakeUpAll()
  192. {
  193. ::WakeAllConditionVariable(&m_cv);
  194. }
  195. private:
  196. void Wait(ICVCondition* pCondition)
  197. {
  198. ASSERT(pCondition);
  199. m_cs.Lock();
  200. while(!pCondition->Detect())
  201. ::SleepConditionVariableCS(&m_cv, m_cs.GetObject(), INFINITE);
  202. }
  203. void Done()
  204. {
  205. m_cs.Unlock();
  206. }
  207. private:
  208. CCVCriSec(const CCVCriSec& cs);
  209. CCVCriSec operator = (const CCVCriSec& cs);
  210. private:
  211. CInterCriSec& m_cs;
  212. CONDITION_VARIABLE m_cv;
  213. };
  214. class CCVSlim
  215. {
  216. public:
  217. CCVSlim(CSlimLock& cs)
  218. : m_cs(cs)
  219. {
  220. ::InitializeConditionVariable(&m_cv);
  221. }
  222. ~CCVSlim() {}
  223. void WaitToRead(ICVCondition* pCondition)
  224. {
  225. ASSERT(pCondition);
  226. m_cs.WaitToRead();
  227. while(!pCondition->Detect())
  228. ::SleepConditionVariableSRW(&m_cv, m_cs.GetObject(), INFINITE, CONDITION_VARIABLE_LOCKMODE_SHARED);
  229. }
  230. void WaitToWrite(ICVCondition* pCondition)
  231. {
  232. ASSERT(pCondition);
  233. m_cs.WaitToWrite();
  234. while(!pCondition->Detect())
  235. ::SleepConditionVariableSRW(&m_cv, m_cs.GetObject(), INFINITE, 0);
  236. }
  237. void ReadDone()
  238. {
  239. m_cs.ReadDone();
  240. }
  241. void WriteDone()
  242. {
  243. m_cs.WriteDone();
  244. }
  245. void WakeUp()
  246. {
  247. ::WakeConditionVariable(&m_cv);
  248. }
  249. void WakeUpAll()
  250. {
  251. ::WakeAllConditionVariable(&m_cv);
  252. }
  253. private:
  254. CCVSlim(const CCVSlim& cs);
  255. CCVSlim operator = (const CCVSlim& cs);
  256. private:
  257. CSlimLock& m_cs;
  258. CONDITION_VARIABLE m_cv;
  259. };
  260. template<class _Lock, class _Var> class CCVGuard
  261. {
  262. public:
  263. void WaitForProduce()
  264. {
  265. m_cvP.WaitToWrite(m_pcdtProduce);
  266. }
  267. void WaitForConsume()
  268. {
  269. m_cvC.WaitToRead(m_pcdtConsume);
  270. }
  271. void ProduceDone()
  272. {
  273. m_cvP.WriteDone();
  274. }
  275. void WakeUpProduce()
  276. {
  277. m_cvP.WakeUp();
  278. }
  279. void ConsumeDone()
  280. {
  281. m_cvC.ReadDone();
  282. }
  283. void WakeUpConsume()
  284. {
  285. m_cvC.WakeUp();
  286. }
  287. void WakeUpAllConsumes()
  288. {
  289. m_cvC.WakeUpAll();
  290. }
  291. public:
  292. CCVGuard(ICVCondition* pcdtProduce, ICVCondition* pcdtConsume)
  293. : m_cvP(m_cs)
  294. , m_cvC(m_cs)
  295. , m_pcdtProduce(pcdtProduce)
  296. , m_pcdtConsume(pcdtConsume)
  297. {
  298. ASSERT(m_pcdtConsume && m_pcdtProduce);
  299. }
  300. ~CCVGuard() {}
  301. private:
  302. CCVGuard(const CCVGuard& cs);
  303. CCVGuard operator = (const CCVGuard& cs);
  304. private:
  305. ICVCondition* m_pcdtProduce;
  306. ICVCondition* m_pcdtConsume;
  307. _Lock m_cs;
  308. _Var m_cvP;
  309. _Var m_cvC;
  310. };
  311. template<class _GuardObj> class CConsumeLock
  312. {
  313. public:
  314. CConsumeLock(_GuardObj& obj) : m_guard(obj) {m_guard.WaitForConsume();}
  315. ~CConsumeLock() {m_guard.ConsumeDone();}
  316. private:
  317. CConsumeLock(const CConsumeLock&);
  318. CConsumeLock operator = (const CConsumeLock&);
  319. private:
  320. _GuardObj& m_guard;
  321. };
  322. template<class _GuardObj> class CProduceLock
  323. {
  324. public:
  325. CProduceLock(_GuardObj& obj) : m_guard(obj) {m_guard.WaitForProduce();}
  326. ~CProduceLock() {m_guard.ProduceDone();}
  327. private:
  328. CProduceLock(const CProduceLock&);
  329. CProduceLock operator = (const CProduceLock&);
  330. private:
  331. _GuardObj& m_guard;
  332. };
  333. typedef CCVGuard<CInterCriSec, CCVCriSec> CCVGuardCS;
  334. typedef CCVGuard<CSlimLock, CCVSlim> CCVGuardSRW;
  335. typedef CProduceLock<CCVGuardCS> CProduceLockCS;
  336. typedef CConsumeLock<CCVGuardCS> CConsumeLockCS;
  337. typedef CProduceLock<CCVGuardSRW> CProduceLockSRW;
  338. typedef CConsumeLock<CCVGuardSRW> CConsumeLockSRW;
  339. #endif