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.

214 lines
5.6 KiB

  1. //
  2. // MODULE: SYNC.CPP
  3. //
  4. // PURPOSE: syncronization classes
  5. //
  6. // COMPANY: Saltmine Creative, Inc. (206)-284-7511 [email protected]
  7. //
  8. // AUTHOR: Oleg Kalosha
  9. //
  10. // ORIGINAL DATE: 8-04-98
  11. //
  12. // NOTES:
  13. //
  14. // Version Date By Comments
  15. //--------------------------------------------------------------------
  16. // V3.0 08-04-98 OK
  17. //
  18. #include "stdafx.h"
  19. #include <algorithm>
  20. #include "sync.h"
  21. #include "event.h"
  22. #include "baseexception.h"
  23. #include "CharConv.h"
  24. #include "apiwraps.h"
  25. ////////////////////////////////////////////////////////////////////////////////////
  26. // CSyncObj
  27. // single sync object abstract class
  28. ////////////////////////////////////////////////////////////////////////////////////
  29. CSyncObj::CSyncObj()
  30. {
  31. // we are to initialize handle in specific inherited class
  32. }
  33. CSyncObj::~CSyncObj()
  34. {
  35. ::CloseHandle(m_handle);
  36. }
  37. HANDLE CSyncObj::GetHandle() const
  38. {
  39. return m_handle;
  40. }
  41. ////////////////////////////////////////////////////////////////////////////////////
  42. // CMutexObj //
  43. // single mutex object class
  44. // Manages a single mutex handle to facilitate waiting for the mutex.
  45. ////////////////////////////////////////////////////////////////////////////////////
  46. CMutexObj::CMutexObj()
  47. : CSyncObj()
  48. {
  49. m_handle = ::CreateMutex(NULL, FALSE, NULL);
  50. }
  51. CMutexObj::~CMutexObj()
  52. {
  53. ::CloseHandle(m_handle);
  54. }
  55. // Smarter strategy here than an infinite wait. Wait up to 60 seconds, then log to event
  56. // log and wait infinitely. If it's logged to event log & eventually gets the mutex,
  57. // it logs to say it finally got the mutex.
  58. void CMutexObj::Lock()
  59. {
  60. WAIT_INFINITE(m_handle);
  61. }
  62. void CMutexObj::Unlock()
  63. {
  64. ::ReleaseMutex(m_handle);
  65. }
  66. ////////////////////////////////////////////////////////////////////////////////////
  67. // CMultiSyncObj //
  68. // multiple sync object abstract class
  69. // Manages multiple handles (the exact type of handle will be determined by a class
  70. // inheriting from this) to facilitate waiting for the union of several events.
  71. ////////////////////////////////////////////////////////////////////////////////////
  72. CMultiSyncObj::CMultiSyncObj()
  73. {
  74. }
  75. CMultiSyncObj::~CMultiSyncObj()
  76. {
  77. }
  78. void CMultiSyncObj::AddHandle(HANDLE handle)
  79. {
  80. vector<HANDLE>::iterator i =
  81. find(m_arrHandle.begin(), m_arrHandle.end(), handle);
  82. if (i == m_arrHandle.end())
  83. {
  84. try
  85. {
  86. m_arrHandle.push_back(handle);
  87. }
  88. catch (exception& x)
  89. {
  90. CString str;
  91. // Note STL exception in event log.
  92. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  93. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  94. SrcLoc.GetSrcFileLineStr(),
  95. CCharConversion::ConvertACharToString(x.what(), str),
  96. _T(""),
  97. EV_GTS_STL_EXCEPTION );
  98. }
  99. }
  100. }
  101. void CMultiSyncObj::RemoveHandle(HANDLE handle)
  102. {
  103. vector<HANDLE>::iterator i =
  104. find(m_arrHandle.begin(), m_arrHandle.end(), handle);
  105. if (i != m_arrHandle.end())
  106. m_arrHandle.erase(i);
  107. }
  108. void CMultiSyncObj::Clear()
  109. {
  110. m_arrHandle.clear();
  111. }
  112. ////////////////////////////////////////////////////////////////////////////////////
  113. // CMultiMutexObj //
  114. // Manages multiple mutex handles to facilitate waiting for the union of several mutexes.
  115. ////////////////////////////////////////////////////////////////////////////////////
  116. CMultiMutexObj::CMultiMutexObj()
  117. : CMultiSyncObj()
  118. {
  119. }
  120. CMultiMutexObj::~CMultiMutexObj()
  121. {
  122. }
  123. // Deprecated use, because it provides inferior logging.
  124. void CMultiMutexObj::Lock()
  125. {
  126. Lock(__FILE__, __LINE__);
  127. }
  128. void CMultiMutexObj::Lock(
  129. LPCSTR srcFile, // Calling source file (__FILE__), used for logging.
  130. // LPCSTR, not LPCTSTR, because __FILE__ is a char*, not a TCHAR*
  131. int srcLine, // Calling source line (__LINE__), used for logging.
  132. DWORD TimeOutVal /*=60000*/ // Time-out interval in milliseconds. After
  133. // this we log an error, then wait infinitely
  134. )
  135. {
  136. CBuildSrcFileLinenoStr SrcLoc( srcFile, srcLine );
  137. DWORD nWaitRetVal= ::WaitForMultipleObjects(
  138. m_arrHandle.size(),
  139. m_arrHandle.begin(),
  140. TRUE, // wait for all objects, not just one.
  141. TimeOutVal);
  142. if (nWaitRetVal == WAIT_FAILED)
  143. {
  144. // very bad news, should never happen
  145. DWORD dwErr = ::GetLastError();
  146. CString strErr;
  147. strErr.Format(_T("%d"), dwErr);
  148. CBuildSrcFileLinenoStr SrcLoc3(__FILE__, __LINE__);
  149. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  150. SrcLoc3.GetSrcFileLineStr(),
  151. _T("Thread wait failed."),
  152. strErr,
  153. EV_GTS_ERROR_STUCK_THREAD );
  154. }
  155. else if (nWaitRetVal == WAIT_TIMEOUT)
  156. {
  157. // Initial wait timed out, note in log, and wait infinitely.
  158. CBuildSrcFileLinenoStr SrcLoc1(__FILE__, __LINE__);
  159. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  160. SrcLoc1.GetSrcFileLineStr(),
  161. _T("Thread wait exceeded initial timeout interval."),
  162. _T(""),
  163. EV_GTS_STUCK_THREAD );
  164. nWaitRetVal= ::WaitForMultipleObjects(
  165. m_arrHandle.size(),
  166. m_arrHandle.begin(),
  167. TRUE, // wait for all objects, not just one.
  168. INFINITE);
  169. // If successfully got what we were waiting for (after logging an apparent
  170. // problem), log the fact that it's ultimately OK.
  171. if (nWaitRetVal == WAIT_OBJECT_0)
  172. {
  173. CBuildSrcFileLinenoStr SrcLoc2(__FILE__, __LINE__);
  174. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  175. SrcLoc2.GetSrcFileLineStr(),
  176. _T("Thread infinite wait succeeded."),
  177. _T(""),
  178. EV_GTS_STUCK_THREAD );
  179. }
  180. }
  181. // Else we don't really care what else ::WaitForMultipleObjects() returns.
  182. // If we get here we got what we were waiting for
  183. }
  184. void CMultiMutexObj::Unlock()
  185. {
  186. for (vector<HANDLE>::iterator i = m_arrHandle.begin();
  187. i != m_arrHandle.end();
  188. i++
  189. )
  190. ::ReleaseMutex(*i);
  191. }