Leaked source code of windows server 2003
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.

219 lines
4.3 KiB

  1. // ReadWriteLock.cpp: implementation of the CReadWriteLock class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "dncmni.h"
  5. #undef DPF_MODNAME
  6. #define DPF_MODNAME "CReadWriteLock::Initialize"
  7. BOOL CReadWriteLock::Initialize()
  8. {
  9. DPF_ENTER();
  10. #ifdef DPNBUILD_ONLYONETHREAD
  11. m_fCritSecInited = TRUE;
  12. #ifdef DBG
  13. m_dwThreadID = 0;
  14. #endif // DBG
  15. #else // ! DPNBUILD_ONLYONETHREAD
  16. m_lReaderCount = 0;
  17. m_lWriterCount = 0;
  18. m_fWriterMode = FALSE;
  19. #ifdef DBG
  20. m_dwWriteThread = 0;
  21. #endif // DBG
  22. if (DNInitializeCriticalSection(&m_csWrite))
  23. {
  24. m_fCritSecInited = TRUE;
  25. }
  26. else
  27. {
  28. // This is necessary in case the user calls Deinitialize.
  29. m_fCritSecInited = FALSE;
  30. }
  31. #endif // ! DPNBUILD_ONLYONETHREAD
  32. DPF_EXIT();
  33. return m_fCritSecInited;
  34. }
  35. #undef DPF_MODNAME
  36. #define DPF_MODNAME "CReadWriteLock::Deinitialize"
  37. VOID CReadWriteLock::Deinitialize()
  38. {
  39. #ifndef DPNBUILD_ONLYONETHREAD
  40. #ifdef DBG
  41. DWORD dwCount;
  42. #endif // DBG
  43. #endif // ! DPNBUILD_ONLYONETHREAD
  44. DPF_ENTER();
  45. #ifdef DPNBUILD_ONLYONETHREAD
  46. if (m_fCritSecInited)
  47. {
  48. #ifdef DBG
  49. DNASSERT(m_dwThreadID == 0);
  50. #endif // DBG
  51. m_fCritSecInited = FALSE;
  52. }
  53. #else // ! DPNBUILD_ONLYONETHREAD
  54. #ifdef DBG
  55. DNASSERT(FALSE == m_fWriterMode);
  56. DNASSERT(0 == m_dwWriteThread);
  57. #endif // DBG
  58. // The counts are decremented after leaving the cs, so these should be
  59. // or going to 0.
  60. #ifdef DBG
  61. dwCount = 0;
  62. #endif // DBG
  63. while (m_lReaderCount)
  64. {
  65. Sleep(0);
  66. #ifdef DBG
  67. dwCount++;
  68. DNASSERT(dwCount < 500);
  69. #endif // DBG
  70. }
  71. #ifdef DBG
  72. dwCount = 0;
  73. #endif // DBG
  74. while (m_lWriterCount)
  75. {
  76. Sleep(0);
  77. #ifdef DBG
  78. dwCount++;
  79. DNASSERT(dwCount < 500);
  80. #endif // DBG
  81. }
  82. if (m_fCritSecInited)
  83. {
  84. DNDeleteCriticalSection(&m_csWrite);
  85. }
  86. #endif // ! DPNBUILD_ONLYONETHREAD
  87. DPF_EXIT();
  88. }
  89. #undef DPF_MODNAME
  90. #define DPF_MODNAME "CReadWriteLock::EnterReadLock"
  91. void CReadWriteLock::EnterReadLock()
  92. {
  93. DPF_ENTER();
  94. DNASSERT(m_fCritSecInited == TRUE);
  95. #ifdef DPNBUILD_ONLYONETHREAD
  96. #ifdef DBG
  97. DNASSERT(m_dwThreadID == 0);
  98. m_dwThreadID = GetCurrentThreadId();
  99. #endif // DBG
  100. #else // ! DPNBUILD_ONLYONETHREAD
  101. // Increment the reader count
  102. DNInterlockedIncrement(&m_lReaderCount);
  103. // Is there a writer waiting?
  104. // As long as there is even one writer waiting,
  105. // Everybody waits on the critical section
  106. if (m_lWriterCount)
  107. {
  108. // Rollback.
  109. DNInterlockedDecrement(&m_lReaderCount);
  110. // We are assured that if every reader is waiting
  111. // on the crit-sec, then readercount will be 0.
  112. DNEnterCriticalSection(&m_csWrite);
  113. DNInterlockedIncrement(&m_lReaderCount);
  114. DNLeaveCriticalSection(&m_csWrite);
  115. }
  116. #ifdef DBG
  117. DNASSERT(GetCurrentThreadId() != m_dwWriteThread);
  118. DNASSERT(FALSE == m_fWriterMode);
  119. #endif // DBG
  120. #endif // ! DPNBUILD_ONLYONETHREAD
  121. DPF_EXIT();
  122. }
  123. #undef DPF_MODNAME
  124. #define DPF_MODNAME "CReadWriteLock::LeaveLock"
  125. void CReadWriteLock::LeaveLock()
  126. {
  127. DPF_ENTER();
  128. DNASSERT(m_fCritSecInited == TRUE);
  129. #ifdef DPNBUILD_ONLYONETHREAD
  130. #ifdef DBG
  131. DNASSERT(m_dwThreadID == GetCurrentThreadId());
  132. m_dwThreadID = 0;
  133. #endif // DBG
  134. #else // ! DPNBUILD_ONLYONETHREAD
  135. if (m_fWriterMode)
  136. {
  137. #ifdef DBG
  138. DNASSERT(GetCurrentThreadId() == m_dwWriteThread);
  139. m_dwWriteThread = 0;
  140. #endif // DBG
  141. m_fWriterMode = FALSE;
  142. DNLeaveCriticalSection(&m_csWrite);
  143. DNInterlockedDecrement(&m_lWriterCount);
  144. }
  145. else
  146. {
  147. DNInterlockedDecrement(&m_lReaderCount);
  148. }
  149. #endif // ! DPNBUILD_ONLYONETHREAD
  150. DPF_EXIT();
  151. }
  152. #undef DPF_MODNAME
  153. #define DPF_MODNAME "CReadWriteLock::EnterWriteLock"
  154. void CReadWriteLock::EnterWriteLock()
  155. {
  156. DPF_ENTER();
  157. DNASSERT(m_fCritSecInited == TRUE);
  158. #ifdef DPNBUILD_ONLYONETHREAD
  159. #ifdef DBG
  160. DNASSERT(m_dwThreadID == 0);
  161. m_dwThreadID = GetCurrentThreadId();
  162. #endif // DBG
  163. #else // ! DPNBUILD_ONLYONETHREAD
  164. // No re-entrance allowed!
  165. #ifdef DBG
  166. DNASSERT(GetCurrentThreadId() != m_dwWriteThread);
  167. #endif // DBG
  168. DNInterlockedIncrement(&m_lWriterCount);
  169. DNEnterCriticalSection(&m_csWrite);
  170. while (m_lReaderCount)
  171. {
  172. Sleep(0);
  173. }
  174. DNASSERT(FALSE == m_fWriterMode);
  175. m_fWriterMode = TRUE;
  176. #ifdef DBG
  177. m_dwWriteThread = GetCurrentThreadId();
  178. #endif // DBG
  179. #endif // ! DPNBUILD_ONLYONETHREAD
  180. DPF_EXIT();
  181. }