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.

168 lines
3.0 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 "qmgrlibp.h"
  15. #include <locks.hxx>
  16. BOOL BITSInitializeCriticalSectionInternal( LPCRITICAL_SECTION lpCriticalSection )
  17. {
  18. __try
  19. {
  20. InitializeCriticalSection( lpCriticalSection ); // SEC: REVIEWED 2002-03-28
  21. }
  22. __except( ( GetExceptionCode() == STATUS_NO_MEMORY ) ?
  23. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH )
  24. {
  25. return FALSE;
  26. }
  27. return TRUE;
  28. }
  29. void BITSIntializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection )
  30. {
  31. if (!BITSInitializeCriticalSectionInternal( lpCriticalSection ) )
  32. throw ComError( E_OUTOFMEMORY );
  33. }
  34. //
  35. // CShareLock methods
  36. //
  37. CSharedLock::CSharedLock()
  38. {
  39. exclusive_owner = 0;
  40. writers = 0;
  41. hevent = INVALID_HANDLE_VALUE; // Flag in the d'tor
  42. BITSIntializeCriticalSection( &lock );
  43. hevent = CreateEvent(0, FALSE, FALSE, 0); // SEC: REVIEWED 2002-03-28
  44. if (0 == hevent)
  45. {
  46. DeleteCriticalSection(&lock);
  47. throw ComError( E_OUTOFMEMORY );
  48. }
  49. }
  50. CSharedLock::~CSharedLock()
  51. {
  52. if (hevent != INVALID_HANDLE_VALUE)
  53. {
  54. DeleteCriticalSection(&lock);
  55. if (hevent) CloseHandle(hevent);
  56. }
  57. }
  58. void
  59. CSharedLock::LockShared()
  60. {
  61. readers++;
  62. if (writers)
  63. {
  64. if ((readers--) == 0)
  65. {
  66. SetEvent(hevent);
  67. }
  68. EnterCriticalSection(&lock);
  69. readers++;
  70. LeaveCriticalSection(&lock);
  71. }
  72. exclusive_owner = 0;
  73. }
  74. void
  75. CSharedLock::UnlockShared(void)
  76. {
  77. ASSERT((LONG)readers > 0);
  78. ASSERT(exclusive_owner == 0);
  79. if ( (readers--) == 0 && writers)
  80. {
  81. SetEvent(hevent);
  82. }
  83. }
  84. void
  85. CSharedLock::LockExclusive(void)
  86. {
  87. EnterCriticalSection(&lock);
  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. ASSERT(HeldExclusive());
  100. ASSERT(writers);
  101. writers--;
  102. exclusive_owner = 0;
  103. LeaveCriticalSection(&lock);
  104. }
  105. void
  106. CSharedLock::Unlock()
  107. {
  108. // Either the lock is held exclusively by this thread or the thread
  109. // has a shared lock. (or the caller has a bug).
  110. if (HeldExclusive())
  111. {
  112. UnlockExclusive();
  113. }
  114. else
  115. {
  116. UnlockShared();
  117. }
  118. }
  119. void
  120. CSharedLock::ConvertToExclusive(void)
  121. {
  122. ASSERT((LONG)readers > 0);
  123. ASSERT(exclusive_owner == 0);
  124. if ( (readers--) == 0 && writers )
  125. SetEvent(hevent);
  126. EnterCriticalSection(&lock);
  127. writers++;
  128. while(readers)
  129. {
  130. WaitForSingleObject(hevent, INFINITE);
  131. }
  132. ASSERT(writers);
  133. exclusive_owner = GetCurrentThreadId();
  134. }