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.

173 lines
3.2 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1995 - 1999
  3. Module Name:
  4. Locks.cxx
  5. Abstract:
  6. Out of line methods for some of the syncronization classes
  7. defined in locks.hxx.
  8. Author:
  9. Mario Goertzel [MarioGo]
  10. Revision History:
  11. MarioGo 03-14-95 Moved from misc.cxx.
  12. MarioGo 01-27-96 Changed from busy (Sleep(0)) wait to event
  13. --*/
  14. #include <precomp.hxx>
  15. #include <locks.hxx>
  16. //
  17. // CShareLock methods
  18. //
  19. #if defined(NTENV) && !defined(_WIN64)
  20. // extern DWORD GetCurrentThreadId(void);
  21. #define GetCurrentThreadId() ((DWORD)NtCurrentTeb()->ClientId.UniqueThread)
  22. #endif
  23. CSharedLock::CSharedLock(RPC_STATUS &status)
  24. {
  25. exclusive_owner = 0;
  26. writers = 0;
  27. hevent = INVALID_HANDLE_VALUE; // Flag in the d'tor
  28. if (status == RPC_S_OK)
  29. {
  30. __try {
  31. InitializeCriticalSection(&lock);
  32. }
  33. __except( GetExceptionCode() == ERROR_OUTOFMEMORY )
  34. {
  35. status = RPC_S_OUT_OF_MEMORY;
  36. }
  37. if (status == RPC_S_OK)
  38. {
  39. hevent = CreateEvent(0, FALSE, FALSE, 0);
  40. if (0 == hevent)
  41. {
  42. status = ERROR_NOT_ENOUGH_MEMORY;
  43. }
  44. }
  45. }
  46. }
  47. CSharedLock::~CSharedLock()
  48. {
  49. if (hevent != INVALID_HANDLE_VALUE)
  50. {
  51. DeleteCriticalSection(&lock);
  52. if (hevent) CloseHandle(hevent);
  53. }
  54. }
  55. void
  56. CSharedLock::LockShared()
  57. {
  58. readers++;
  59. LogEvent(SU_MUTEX, EV_INC, this, 0, readers);
  60. if (writers)
  61. {
  62. if ((readers--) == 0)
  63. {
  64. SetEvent(hevent);
  65. }
  66. EnterCriticalSection(&lock);
  67. readers++;
  68. LeaveCriticalSection(&lock);
  69. }
  70. exclusive_owner = 0;
  71. }
  72. void
  73. CSharedLock::UnlockShared(void)
  74. {
  75. ASSERT((LONG)readers > 0);
  76. ASSERT(exclusive_owner == 0);
  77. if ( (readers--) == 0 && writers)
  78. {
  79. SetEvent(hevent);
  80. }
  81. LogEvent(SU_MUTEX, EV_DEC, this, 0, readers);
  82. }
  83. void
  84. CSharedLock::LockExclusive(void)
  85. {
  86. EnterCriticalSection(&lock);
  87. LogEvent(SU_MUTEX, EV_INC, this, ULongToPtr(0x99999999), writers+1);
  88. writers++;
  89. while(readers)
  90. {
  91. WaitForSingleObject(hevent, INFINITE);
  92. }
  93. ASSERT(writers);
  94. exclusive_owner = GetCurrentThreadId();
  95. }
  96. void
  97. CSharedLock::UnlockExclusive(void)
  98. {
  99. LogEvent(SU_MUTEX, EV_DEC, this, ULongToPtr(0x99999999), writers-1);
  100. ASSERT(HeldExclusive());
  101. ASSERT(writers);
  102. writers--;
  103. exclusive_owner = 0;
  104. LeaveCriticalSection(&lock);
  105. }
  106. void
  107. CSharedLock::Unlock()
  108. {
  109. // Either the lock is held exclusively by this thread or the thread
  110. // has a shared lock. (or the caller has a bug).
  111. if (HeldExclusive())
  112. {
  113. UnlockExclusive();
  114. }
  115. else
  116. {
  117. UnlockShared();
  118. }
  119. }
  120. void
  121. CSharedLock::ConvertToExclusive(void)
  122. {
  123. ASSERT((LONG)readers > 0);
  124. ASSERT(exclusive_owner == 0);
  125. if ( (readers--) == 0 && writers )
  126. SetEvent(hevent);
  127. EnterCriticalSection(&lock);
  128. writers++;
  129. while(readers)
  130. {
  131. WaitForSingleObject(hevent, INFINITE);
  132. }
  133. ASSERT(writers);
  134. exclusive_owner = GetCurrentThreadId();
  135. }