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.

154 lines
3.8 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // SpinLock.h
  7. //
  8. // Description:
  9. // Spin Lock implementation.
  10. //
  11. // Maintained By:
  12. // Geoffrey Pease (GPease) 27-NOV-1999
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. #pragma once
  16. // CSpinLock
  17. class
  18. CSpinLock
  19. {
  20. private: // Data
  21. LONG * m_plLock; // pointer to the lock
  22. LONG m_lSpinCount; // counts the number of sleeps
  23. LONG m_lTimeout; // count until acquire lock fails
  24. #if DBG==1
  25. BOOL m_fAcquired; // DEBUG: internal state of the lock
  26. BOOL m_fAcquiredOnce; // DEBUG: lock was acquired at least once.
  27. #endif
  28. public: // Methods
  29. explicit
  30. CSpinLock( LONG * plLock, LONG lTimeout ) :
  31. m_plLock( plLock ),
  32. m_lTimeout( lTimeout )
  33. {
  34. Assert( m_lTimeout >= 0 || m_lTimeout == INFINITE );
  35. #if DBG==1
  36. m_fAcquired = FALSE;
  37. m_fAcquiredOnce = FALSE;
  38. #endif
  39. };
  40. //
  41. ~CSpinLock()
  42. {
  43. #if DBG==1
  44. AssertMsg( m_fAcquired == FALSE, "Lock was not released!" );
  45. AssertMsg( m_fAcquiredOnce != FALSE, "Lock was never acquired. Why was I needed?" );
  46. #endif
  47. };
  48. //////////////////////////////////////////////////////////////////////////
  49. //
  50. // HRESULT
  51. // AcquireLock( void )
  52. //
  53. // Description:
  54. // Acquires the spin lock. Does not return until the lock is
  55. // acquired.
  56. //
  57. // Arguments:
  58. // None.
  59. //
  60. // Return Values:
  61. // S_OK - Sucess.
  62. // HRESULT_FROM_WIN32( ERROR_LOCK_FAILED ) - Lock failed.
  63. //
  64. //////////////////////////////////////////////////////////////////////////
  65. HRESULT
  66. AcquireLock( void )
  67. {
  68. HRESULT hr;
  69. LONG l = TRUE;
  70. #if DBG==1
  71. AssertMsg( m_fAcquired == FALSE, "Trying to acquire a lock that it already own. Thread is going to freeze up." );
  72. m_fAcquiredOnce = TRUE;
  73. #endif
  74. m_lSpinCount = 0;
  75. for(;;)
  76. {
  77. l = InterlockedCompareExchange( m_plLock, TRUE, FALSE );
  78. if ( l == FALSE )
  79. {
  80. //
  81. // Lock acquired.
  82. //
  83. hr = S_OK;
  84. break;
  85. } // if: got lock
  86. else
  87. {
  88. m_lSpinCount++;
  89. if ( m_lSpinCount > m_lTimeout )
  90. {
  91. AssertMsg( m_lSpinCount >= 0, "This lock doesn't seem to have been released properly." );
  92. if ( m_lTimeout != INFINITE )
  93. {
  94. hr = THR( HRESULT_FROM_WIN32( ERROR_LOCK_FAILED ) );
  95. break;
  96. } // if: not infinite
  97. } // if: count exceeded
  98. //
  99. // Put a breakpoint here if you think that someone is double
  100. // locking.
  101. //
  102. Sleep( 1 );
  103. } // if: lock not acquired
  104. } // for: forever
  105. #if DBG==1
  106. m_fAcquired = TRUE;
  107. #endif
  108. return hr;
  109. }; // AcquireLock( )
  110. //////////////////////////////////////////////////////////////////////////
  111. //
  112. // HRESULT
  113. // ReleaseLock( void )
  114. //
  115. // Description:
  116. // Releases the spin lock. Return immediately.
  117. //
  118. // Arguments:
  119. // None.
  120. //
  121. // Return Values:
  122. // S_OK - Success.
  123. //
  124. //////////////////////////////////////////////////////////////////////////
  125. HRESULT
  126. ReleaseLock( void )
  127. {
  128. #if DBG==1
  129. AssertMsg( m_fAcquired == TRUE, "Releasing a lock that was not owned." );
  130. #endif
  131. *m_plLock = FALSE;
  132. #if DBG==1
  133. m_fAcquired = FALSE;
  134. #endif
  135. return S_OK;
  136. }; // ReleaseLock( )
  137. }; // class CSpinLock