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.

129 lines
3.2 KiB

  1. // this lock only works for a single write, and multiple read, concurrent
  2. // multiple exclusive lock isn't a supported scenario
  3. //
  4. // (1) ClaimExclusiveLock() and ClaimShareLock() is mutually exclusive because
  5. // the reverse order of increments and checking
  6. //
  7. // (2) As soon as Exclusive is set, all new Share lock will be blocked
  8. //
  9. //
  10. #ifndef _CReadWriteLock_H_
  11. #define _CReadWriteLock_H_
  12. class CReadWriteLock
  13. {
  14. long lExclusive;
  15. long lTotalUsers;
  16. long lReadInQueue;
  17. HANDLE hWriteReadyEvent, hReadReadyEvent;
  18. public:
  19. CReadWriteLock()
  20. {
  21. hWriteReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  22. hReadReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  23. };
  24. ~CReadWriteLock()
  25. {
  26. CloseHandle(hWriteReadyEvent);
  27. CloseHandle(hReadReadyEvent);
  28. }
  29. bool IsInit()
  30. {
  31. return NULL != hWriteReadyEvent && NULL != hReadReadyEvent;
  32. }
  33. bool CReadWriteLock::ClaimExclusiveLock()
  34. {
  35. ResetEvent(hWriteReadyEvent);
  36. ResetEvent(hReadReadyEvent);
  37. InterlockedIncrement( &lExclusive );
  38. InterlockedIncrement( &lTotalUsers );
  39. if (lTotalUsers > 1)
  40. {
  41. if (lReadInQueue > 0) // in case no body is in the read queue
  42. {
  43. // wait until all the reads to finish
  44. if (WAIT_OBJECT_0 != WaitForSingleObject(hWriteReadyEvent, INFINITE))
  45. return false;
  46. }
  47. }
  48. return true;
  49. }
  50. void CReadWriteLock::ReleaseExclusiveLock( )
  51. {
  52. InterlockedDecrement( &lTotalUsers );
  53. InterlockedDecrement( &lExclusive );
  54. SetEvent(hReadReadyEvent);
  55. }
  56. bool CReadWriteLock::ClaimShareLock( )
  57. {
  58. InterlockedIncrement( &lTotalUsers );
  59. if (CReadWriteLock::lExclusive > 0)
  60. {
  61. if (WAIT_OBJECT_0 != WaitForSingleObject(hReadReadyEvent, INFINITE))
  62. return false;
  63. }
  64. InterlockedIncrement ( &lReadInQueue );
  65. return true;
  66. }
  67. void CReadWriteLock::ReleaseShareLock( )
  68. {
  69. if (0 == InterlockedDecrement ( &lReadInQueue ))
  70. {
  71. if (CReadWriteLock::lExclusive > 0)
  72. SetEvent(hWriteReadyEvent);
  73. }
  74. InterlockedDecrement( &lTotalUsers );
  75. }
  76. };
  77. //
  78. // this class extends CReadWriteLock to allow multiple write threads
  79. // -- additional overhead of entering/leaving critical section
  80. //
  81. class CReadWriteLockEx : public CReadWriteLock
  82. {
  83. public:
  84. bool ClaimExclusiveLock()
  85. {
  86. // Request ownership of the critical section.
  87. EnterCriticalSection(&CriticalSection);
  88. return CReadWriteLock::ClaimExclusiveLock();
  89. };
  90. void ReleaseExclusiveLock( )
  91. {
  92. CReadWriteLock::ReleaseExclusiveLock();
  93. // Release ownership of the critical section.
  94. LeaveCriticalSection(&CriticalSection);
  95. };
  96. public:
  97. // constructor and desctructor
  98. CReadWriteLockEx()
  99. {
  100. // Initialize the critical section.
  101. InitializeCriticalSection(&CriticalSection);
  102. };
  103. virtual ~CReadWriteLockEx()
  104. {
  105. // Release resources used by the critical section object.
  106. DeleteCriticalSection(&CriticalSection);
  107. };
  108. protected:
  109. // data members
  110. CRITICAL_SECTION CriticalSection;
  111. };
  112. #endif