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.

293 lines
7.3 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. LOCK.H
  5. Abstract:
  6. Generic class for obtaining read and write locks to some resource.
  7. See lock.h for all documentation.
  8. Classes defined:
  9. CLock
  10. History:
  11. a-levn 5-Sept-96 Created.
  12. 3/10/97 a-levn Fully documented
  13. --*/
  14. #ifndef __GATEWAY__LOCK__H_
  15. #define __GATEWAY__LOCK__H_
  16. #include <corepol.h>
  17. #include <lockst.h>
  18. #include <statsync.h>
  19. #ifdef DBG
  20. class OperationStat
  21. {
  22. enum { HistoryLength = 122 };
  23. DWORD signature;
  24. DWORD historycData_[HistoryLength];
  25. DWORD historyIndex_;
  26. DWORD opCount_;
  27. DWORD avgTime_;
  28. DWORD maxTime_;
  29. LONG zeroTime_;
  30. public:
  31. static CStaticCritSec lock_;
  32. OperationStat() :
  33. historyIndex_(0), opCount_(0), avgTime_(0), maxTime_(0),signature((DWORD)'nCpO')
  34. {
  35. memset(historycData_, 0, sizeof(historycData_));
  36. };
  37. void addTime(DWORD duration)
  38. {
  39. if (duration==0)
  40. {
  41. InterlockedIncrement(&zeroTime_);
  42. return;
  43. }
  44. if (CStaticCritSec::anyFailure()) return ;
  45. EnterCriticalSection(&lock_);
  46. historycData_[historyIndex_++]=duration;
  47. historyIndex_%=HistoryLength;
  48. if (++opCount_ == 0) ++opCount_;
  49. double avg = (double)avgTime_ + ((double)duration-avgTime_ )/opCount_;
  50. avgTime_ = (DWORD)avg;
  51. if (duration > maxTime_)
  52. {
  53. maxTime_ = duration;
  54. };
  55. LeaveCriticalSection(&lock_);
  56. };
  57. };
  58. extern OperationStat gTimeTraceReadLock;
  59. extern OperationStat gTimeTraceWriteLock;
  60. extern OperationStat gTimeTraceBackupLock;
  61. class TimeTrace
  62. {
  63. DWORD start_;
  64. public:
  65. TimeTrace( ):
  66. start_(GetTickCount())
  67. { }
  68. ~TimeTrace()
  69. {
  70. gTimeTraceBackupLock.addTime(GetTickCount()-start_);
  71. }
  72. };
  73. #define TIMETRACEBACKUP TimeTrace timeTrace;
  74. #else
  75. #define TIMETRACEBACKUP
  76. #endif
  77. //*****************************************************************************
  78. //
  79. // class CLock
  80. //
  81. // Generic class for obtaining read and write locks to some resource.
  82. // Simultaneous reads are allowed, but no concurrent writes or concurrent
  83. // read and write accesses are.
  84. //
  85. // NOTE: this class is for in-process sinchronization only!
  86. //
  87. // Usage: create an instance of this class and share it among the accessing
  88. // threads. Threads must call member functions of the same instance to
  89. // obtain and release locks.
  90. //
  91. //*****************************************************************************
  92. //
  93. // ReadLock
  94. //
  95. // Use this function to request read access to the resource. Access will be
  96. // granted once no threads are writing on the resource. You must call
  97. // ReadUnlock once you are done reading.
  98. //
  99. // Parameters:
  100. //
  101. // DWORD dwTimeout The number of milliseconds to wait for access.
  102. // If access is still unavailable after this time,
  103. // an error is returned.
  104. // Returns:
  105. //
  106. // NoError On Success
  107. // TimedOut On timeout.
  108. // Failed On system error
  109. //
  110. //*****************************************************************************
  111. //
  112. // ReadUnlock
  113. //
  114. // Use this function to release a read lock on the resource. No check is
  115. // performed to assertain that this thread holds a lock. Unmatched calls to
  116. // ReadUnlock may lead to lock integrity violations!
  117. //
  118. // Returns:
  119. //
  120. // NoError On success
  121. // Failed On system error or unmatched call.
  122. //
  123. //*****************************************************************************
  124. //
  125. // WriteLock
  126. //
  127. // Use this function to request write access to the resource. Access will be
  128. // granted once no threads are reading or writing on the resource. You must
  129. // call WriteUnlock once you are done writing.
  130. //
  131. // Parameters:
  132. //
  133. // DWORD dwTimeout The number of milliseconds to wait for access.
  134. // If access is still unavailable after this time,
  135. // an error is returned.
  136. // Returns:
  137. //
  138. // NoError On Success
  139. // TimedOut On timeout.
  140. // Failed On system error
  141. //
  142. //*****************************************************************************
  143. //
  144. // WriteUnlock
  145. //
  146. // Use this function to release a write lock on the resource. No check is
  147. // performed to assertain that this thread holds a lock. Unmatched calls to
  148. // WriteUnlock may lead to lock integrity violations!
  149. //
  150. // Returns:
  151. //
  152. // NoError On success
  153. // Failed On system error or unmatched call.
  154. //
  155. //*****************************************************************************
  156. //
  157. // DowngradeLock
  158. //
  159. // Use this function to "convert" a Write lock into a Read lock. That is, if
  160. // you are currently holding a write lock and call DowngradeLock, you will
  161. // be holding a read lock with the guarantee that no one wrote anything between
  162. // the unlock and the lock
  163. //
  164. // Returns:
  165. //
  166. // NoError On Success
  167. // Failed On system error or unmatched call
  168. //
  169. //******************************************************************************
  170. class CLock
  171. {
  172. public:
  173. enum { NoError = 0, TimedOut, Failed };
  174. int ReadLock(DWORD dwTimeout = INFINITE);
  175. int ReadUnlock();
  176. int WriteLock(DWORD dwTimeout = INFINITE);
  177. int WriteUnlock();
  178. int DowngradeLock();
  179. CLock();
  180. ~CLock();
  181. protected:
  182. int WaitFor(HANDLE hEvent, DWORD dwTimeout);
  183. protected:
  184. int m_nWriting;
  185. int m_nReading;
  186. int m_nWaitingToWrite;
  187. int m_nWaitingToRead;
  188. CriticalSection m_csEntering;
  189. CriticalSection m_csAll;
  190. HANDLE m_hCanWrite;
  191. HANDLE m_hCanRead;
  192. DWORD m_WriterId;
  193. //CFlexArray m_adwReaders;
  194. enum { MaxRegistredReaders = 16,
  195. MaxTraceSize = 7};
  196. DWORD m_dwArrayIndex;
  197. struct {
  198. DWORD ThreadId;
  199. //PVOID Trace[MaxTraceSize];
  200. } m_adwReaders[MaxRegistredReaders];
  201. };
  202. #ifdef DBG
  203. class CAutoReadLock
  204. {
  205. DWORD start;
  206. public:
  207. CAutoReadLock(CLock *lock) : m_lock(lock), m_bLocked(FALSE) { }
  208. ~CAutoReadLock() { Unlock(); }
  209. void Unlock() {if ( m_bLocked) { m_lock->ReadUnlock(); m_bLocked = FALSE; gTimeTraceReadLock.addTime(GetTickCount()-start);} }
  210. bool Lock() {if (!m_bLocked) { start = GetTickCount(); return m_bLocked = (CLock::NoError == m_lock->ReadLock()) ; } else {return false;}; }
  211. private:
  212. CLock *m_lock;
  213. BOOL m_bLocked;
  214. };
  215. class CAutoWriteLock
  216. {
  217. DWORD start;
  218. public:
  219. CAutoWriteLock(CLock *lock) : m_lock(lock), m_bLocked(FALSE) { }
  220. ~CAutoWriteLock() { Unlock(); }
  221. void Unlock() {if ( m_bLocked) { m_lock->WriteUnlock(); m_bLocked = FALSE; gTimeTraceWriteLock.addTime(GetTickCount()-start);} }
  222. bool Lock() {if (!m_bLocked) { start = GetTickCount(); return m_bLocked = (CLock::NoError == m_lock->WriteLock()); } else { return false; }; }
  223. private:
  224. CLock *m_lock;
  225. BOOL m_bLocked;
  226. };
  227. #else
  228. class CAutoReadLock
  229. {
  230. public:
  231. CAutoReadLock(CLock *lock) : m_lock(lock), m_bLocked(FALSE) { }
  232. ~CAutoReadLock() { Unlock(); }
  233. void Unlock() {if ( m_bLocked) { m_lock->ReadUnlock(); m_bLocked = FALSE; } }
  234. bool Lock() {if (!m_bLocked) { return m_bLocked = (CLock::NoError == m_lock->ReadLock()) ; } else {return false;}; }
  235. private:
  236. CLock *m_lock;
  237. BOOL m_bLocked;
  238. };
  239. class CAutoWriteLock
  240. {
  241. public:
  242. CAutoWriteLock(CLock *lock) : m_lock(lock), m_bLocked(FALSE) { }
  243. ~CAutoWriteLock() { Unlock(); }
  244. void Unlock() {if ( m_bLocked) { m_lock->WriteUnlock(); m_bLocked = FALSE; } }
  245. bool Lock() {if (!m_bLocked) { return m_bLocked = (CLock::NoError == m_lock->WriteLock()); } else { return false; }; }
  246. private:
  247. CLock *m_lock;
  248. BOOL m_bLocked;
  249. };
  250. #endif
  251. #endif