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

513 lines
10 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-1998
  5. //
  6. // File:
  7. //
  8. // Contents:
  9. //
  10. // History: 12-09-97 HueiWang
  11. //
  12. //---------------------------------------------------------------------------
  13. #ifndef __LS_LOCKS_H
  14. #define __LS_LOCKS_H
  15. #include <windows.h>
  16. #include "assert.h"
  17. #define ARRAY_COUNT(a) sizeof(a) / sizeof(a[0])
  18. typedef enum { WRITER_LOCK, READER_LOCK, NO_LOCK } RWLOCK_TYPE;
  19. //-------------------------------------------------------------------------
  20. template <int init_count, int max_count>
  21. class CTSemaphore {
  22. private:
  23. HANDLE m_semaphore;
  24. public:
  25. CTSemaphore() : m_semaphore(NULL)
  26. {
  27. m_semaphore=CreateSemaphore(NULL, init_count, max_count, NULL);
  28. assert(m_semaphore != NULL);
  29. }
  30. ~CTSemaphore()
  31. {
  32. if(m_semaphore)
  33. CloseHandle(m_semaphore);
  34. }
  35. DWORD Acquire(int WaitTime=INFINITE, BOOL bAlertable=FALSE)
  36. {
  37. return WaitForSingleObjectEx(m_semaphore, WaitTime, bAlertable);
  38. }
  39. BOOL
  40. AcquireEx(
  41. HANDLE hHandle,
  42. int dwWaitTime=INFINITE,
  43. BOOL bAlertable=FALSE
  44. )
  45. /*++
  46. --*/
  47. {
  48. BOOL bSuccess = TRUE;
  49. DWORD dwStatus;
  50. HANDLE hHandles[] = {m_semaphore, hHandle};
  51. if(hHandle == NULL || hHandle == INVALID_HANDLE_VALUE)
  52. {
  53. SetLastError(ERROR_INVALID_PARAMETER);
  54. bSuccess = FALSE;
  55. }
  56. else
  57. {
  58. dwStatus = WaitForMultipleObjectsEx(
  59. sizeof(hHandles)/sizeof(hHandles[0]),
  60. hHandles,
  61. FALSE,
  62. dwWaitTime,
  63. bAlertable
  64. );
  65. if(dwStatus != WAIT_OBJECT_0)
  66. {
  67. bSuccess = FALSE;
  68. }
  69. }
  70. return bSuccess;
  71. }
  72. BOOL Release(long count=1)
  73. {
  74. return ReleaseSemaphore(m_semaphore, count, NULL);
  75. }
  76. BOOL IsGood()
  77. {
  78. return m_semaphore != NULL;
  79. }
  80. };
  81. //-------------------------------------------------------------------------
  82. class CCriticalSection {
  83. CRITICAL_SECTION m_CS;
  84. BOOL m_bGood;
  85. public:
  86. CCriticalSection(
  87. DWORD dwSpinCount = 4000 // see InitializeCriticalSection...
  88. ) : m_bGood(TRUE)
  89. {
  90. __try {
  91. InitializeCriticalSectionAndSpinCount(&m_CS, dwSpinCount);
  92. }
  93. __except(EXCEPTION_EXECUTE_HANDLER)
  94. {
  95. SetLastError(GetExceptionCode());
  96. m_bGood = FALSE;
  97. }
  98. }
  99. ~CCriticalSection()
  100. {
  101. if(IsGood() == TRUE)
  102. {
  103. DeleteCriticalSection(&m_CS);
  104. }
  105. }
  106. BOOL
  107. IsGood() { return m_bGood; }
  108. void Lock()
  109. {
  110. EnterCriticalSection(&m_CS);
  111. }
  112. void UnLock()
  113. {
  114. LeaveCriticalSection(&m_CS);
  115. }
  116. BOOL TryLock()
  117. {
  118. return TryEnterCriticalSection(&m_CS);
  119. }
  120. };
  121. //--------------------------------------------------------------------------
  122. class CCriticalSectionLocker {
  123. public:
  124. CCriticalSectionLocker( CCriticalSection& m ) : m_cs(m)
  125. {
  126. m.Lock();
  127. }
  128. ~CCriticalSectionLocker()
  129. {
  130. m_cs.UnLock();
  131. }
  132. private:
  133. CCriticalSection& m_cs;
  134. };
  135. //-----------------------------------------------------------
  136. class CSafeCounter {
  137. private:
  138. //CCriticalSection m_cs;
  139. long m_Counter;
  140. //inline void
  141. //Lock()
  142. //{
  143. // m_cs.Lock();
  144. //}
  145. //inline void
  146. //Unlock()
  147. //{
  148. // m_cs.UnLock();
  149. //}
  150. public:
  151. CSafeCounter(
  152. long init_value=0
  153. ) :
  154. m_Counter(init_value)
  155. /*++
  156. --*/
  157. {
  158. }
  159. ~CSafeCounter()
  160. {
  161. }
  162. operator+=(long dwValue)
  163. {
  164. long dwNewValue;
  165. //Lock();
  166. //dwNewValue = (m_Counter += dwValue);
  167. //Unlock();
  168. //return dwNewValue;
  169. dwNewValue = InterlockedExchangeAdd( &m_Counter, dwValue );
  170. return dwNewValue += dwValue;
  171. }
  172. operator-=(long dwValue)
  173. {
  174. long dwNewValue;
  175. //Lock();
  176. //dwNewValue = (m_Counter -= dwValue);
  177. //Unlock();
  178. //return dwNewValue;
  179. dwNewValue = InterlockedExchangeAdd( &m_Counter, -dwValue );
  180. return dwNewValue -= dwValue;
  181. }
  182. operator++()
  183. {
  184. //long dwValue;
  185. //Lock();
  186. //dwValue = ++m_Counter;
  187. //Unlock();
  188. //return dwValue;
  189. return InterlockedIncrement(&m_Counter);
  190. }
  191. operator++(int)
  192. {
  193. //long dwValue;
  194. //Lock();
  195. //dwValue = m_Counter++;
  196. //Unlock();
  197. //return dwValue;
  198. long lValue;
  199. lValue = InterlockedIncrement(&m_Counter);
  200. return --lValue;
  201. }
  202. operator--()
  203. {
  204. //long dwValue;
  205. //Lock();
  206. //dwValue = --m_Counter;
  207. //Unlock();
  208. //return dwValue;
  209. return InterlockedDecrement(&m_Counter);
  210. }
  211. operator--(int)
  212. {
  213. //long dwValue;
  214. //Lock();
  215. //dwValue = m_Counter--;
  216. //Unlock();
  217. //return dwValue;
  218. long lValue;
  219. lValue = InterlockedDecrement(&m_Counter);
  220. return ++lValue;
  221. }
  222. operator long()
  223. {
  224. //long lValue;
  225. //Lock();
  226. //lValue = m_Counter;
  227. //Unlock();
  228. //return lValue;
  229. return InterlockedExchange(&m_Counter, m_Counter);
  230. }
  231. //operator DWORD()
  232. //{
  233. // long dwValue;
  234. // Lock();
  235. // dwValue = m_Counter;
  236. // Unlock();
  237. // return dwValue;
  238. //}
  239. operator=(const long dwValue)
  240. {
  241. //Lock();
  242. //m_Counter = dwValue;
  243. //Unlock();
  244. //return dwValue;
  245. InterlockedExchange(&m_Counter, dwValue);
  246. return dwValue;
  247. }
  248. };
  249. //-------------------------------------------------------------------------
  250. // HueiWang 12/23/97 need more testing...
  251. class CRWLock
  252. {
  253. private:
  254. HANDLE hMutex;
  255. HANDLE hWriterMutex;
  256. HANDLE hReaderEvent;
  257. long iReadCount;
  258. long iWriteCount;
  259. long iReadEntry;
  260. long iWriteEntry;
  261. public:
  262. CRWLock()
  263. {
  264. BOOL bSuccess=Init();
  265. assert(bSuccess == TRUE);
  266. }
  267. ~CRWLock()
  268. {
  269. Cleanup();
  270. }
  271. //-----------------------------------------------------------
  272. BOOL
  273. Init()
  274. {
  275. hReaderEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
  276. hMutex = CreateEvent(NULL,FALSE,TRUE,NULL);
  277. hWriterMutex = CreateMutex(NULL,FALSE,NULL);
  278. if(!hReaderEvent || !hMutex || !hWriterMutex)
  279. return FALSE;
  280. iReadCount = -1;
  281. iWriteCount = -1;
  282. iReadEntry = 0;
  283. iWriteEntry = 0;
  284. return (TRUE);
  285. }
  286. //-----------------------------------------------------------
  287. void
  288. Cleanup()
  289. {
  290. CloseHandle(hReaderEvent);
  291. CloseHandle(hMutex);
  292. CloseHandle(hWriterMutex);
  293. iReadCount = -1;
  294. iWriteCount = -1;
  295. iReadEntry = 0;
  296. iWriteEntry = 0;
  297. }
  298. //-----------------------------------------------------------
  299. void
  300. Acquire(
  301. RWLOCK_TYPE lockType
  302. )
  303. /*++
  304. ++*/
  305. {
  306. if (lockType == WRITER_LOCK)
  307. {
  308. InterlockedIncrement(&iWriteCount);
  309. WaitForSingleObject(hWriterMutex,INFINITE);
  310. WaitForSingleObject(hMutex, INFINITE);
  311. assert(InterlockedIncrement(&iWriteEntry) == 1);
  312. assert(InterlockedExchange(&iReadEntry, iReadEntry) == 0);
  313. }
  314. else
  315. {
  316. if (InterlockedIncrement(&iReadCount) == 0)
  317. {
  318. WaitForSingleObject(hMutex, INFINITE);
  319. SetEvent(hReaderEvent);
  320. }
  321. WaitForSingleObject(hReaderEvent,INFINITE);
  322. InterlockedIncrement(&iReadEntry);
  323. assert(InterlockedExchange(&iWriteEntry, iWriteEntry) == 0);
  324. }
  325. }
  326. //-----------------------------------------------------------
  327. void
  328. Release(
  329. RWLOCK_TYPE lockType
  330. )
  331. /*++
  332. ++*/
  333. {
  334. if (lockType == WRITER_LOCK)
  335. {
  336. InterlockedDecrement(&iWriteEntry);
  337. InterlockedDecrement(&iWriteCount);
  338. SetEvent(hMutex);
  339. ReleaseMutex(hWriterMutex);
  340. }
  341. else if(lockType == READER_LOCK)
  342. {
  343. InterlockedDecrement(&iReadEntry);
  344. if (InterlockedDecrement(&iReadCount) < 0)
  345. {
  346. ResetEvent(hReaderEvent);
  347. SetEvent(hMutex);
  348. }
  349. }
  350. }
  351. long GetReadCount()
  352. {
  353. return iReadCount+1;
  354. }
  355. long GetWriteCount()
  356. {
  357. return iWriteCount+1;
  358. }
  359. };
  360. //---------------------------------------------------------------------
  361. //
  362. //
  363. class CCMutex {
  364. public:
  365. HANDLE hMutex;
  366. CCMutex() : hMutex(NULL) {
  367. hMutex=CreateMutex(NULL, FALSE, NULL);
  368. }
  369. ~CCMutex() {
  370. CloseHandle(hMutex);
  371. }
  372. DWORD Lock(
  373. DWORD dwWaitTime=INFINITE,
  374. BOOL bAlertable=FALSE
  375. )
  376. {
  377. return WaitForSingleObjectEx(
  378. hMutex,
  379. dwWaitTime,
  380. bAlertable);
  381. }
  382. BOOL Unlock() {
  383. return ReleaseMutex(hMutex);
  384. }
  385. };
  386. //---------------------------------------------------------------------------------
  387. class CCEvent {
  388. BOOL bManual;
  389. public:
  390. HANDLE hEvent;
  391. CCEvent(
  392. BOOL bManual,
  393. BOOL bInitState) :
  394. hEvent(NULL),
  395. bManual(bManual)
  396. {
  397. hEvent=CreateEvent(
  398. NULL,
  399. bManual,
  400. bInitState,
  401. NULL);
  402. }
  403. ~CCEvent() {
  404. CloseHandle(hEvent);
  405. }
  406. DWORD Lock( DWORD dwWaitTime=INFINITE,
  407. BOOL bAlertable=FALSE)
  408. {
  409. return WaitForSingleObjectEx(
  410. hEvent,
  411. dwWaitTime,
  412. bAlertable);
  413. }
  414. BOOL SetEvent() {
  415. return ::SetEvent(hEvent);
  416. }
  417. BOOL ResetEvent() {
  418. return ::ResetEvent(hEvent);
  419. }
  420. BOOL PulseEvent() {
  421. return ::PulseEvent(hEvent);
  422. }
  423. BOOL IsManual() {
  424. return bManual;
  425. }
  426. };
  427. #endif