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.

419 lines
14 KiB

  1. ///+---------------------------------------------------------------------------
  2. //
  3. // File: olesem.hxx
  4. //
  5. // Contents: Semaphore classes for use in OLE code
  6. //
  7. // Classes: COleStaticMutexSem - Mutex semaphore class for statically
  8. // allocated objects
  9. // COleDebugMutexSem - Mutex semaphore class for statically
  10. // allocated objects that are not destructed
  11. // on DLL unload (and thus are leaks..used
  12. // for trace packages and such).
  13. //
  14. // History: 14-Dec-95 Jeffe Initial entry, derived from
  15. // sem32.hxx by AlexT.
  16. //
  17. // Notes: This module defines a set of classes to wrap WIN32
  18. // Critical Sections.
  19. //
  20. // Note the distinction of allocation class: the reason for this
  21. // is to avoid static constructors and destructors.
  22. //
  23. // The classes in this module *must* be used for mutex semaphores
  24. // that are statically allocated. Use the classes in sem32.hxx
  25. // for dynamically allocated (from heap or on the stack) objects.
  26. //
  27. //----------------------------------------------------------------------------
  28. #ifndef __OLESEM_HXX__
  29. #define __OLESEM_HXX__
  30. #include <windows.h>
  31. #if LOCK_PERF==1
  32. #include <lockperf.hxx>
  33. #endif
  34. //+---------------------------------------------------------------------------
  35. //
  36. // Macros for use in the code.
  37. //
  38. //----------------------------------------------------------------------------
  39. #if DBG==1
  40. #if LOCK_PERF==1
  41. #define LOCK_WRITE(mxs) mxs.AcquireWriterLock(__FILE__, __LINE__, #mxs)
  42. #define LOCK_READ(mxs) mxs.AcquireReaderLock(__FILE__, __LINE__, #mxs)
  43. #else
  44. #define LOCK_WRITE(mxs) mxs.AcquireWriterLock()
  45. #define LOCK_READ(mxs) mxs.AcquireReaderLock()
  46. #endif
  47. #define LOCK(mxs) mxs.Request(__FILE__, __LINE__, #mxs)
  48. #define UNLOCK_WRITE(mxs) mxs.ReleaseWriterLock()
  49. #define UNLOCK_READ(mxs) mxs.ReleaseReaderLock()
  50. #define UNLOCK(mxs) mxs.Release()
  51. #if LOCK_PERF==1
  52. #define LOCK_UPGRADE(mxs, ck, f) mxs.UpgradeToWriterLock(ck, f, __FILE__, __LINE__, #mxs)
  53. #define LOCK_DOWNGRADE(mxs, ck) mxs.DowngradeFromWriterLock(ck, __FILE__, __LINE__, #mxs)
  54. #define LOCK_RESTORE(mxs, ck) mxs.RestoreLock(ck, NULL, __FILE__, __LINE__, #mxs)
  55. #else
  56. #define LOCK_UPGRADE(mxs, ck, f) mxs.UpgradeToWriterLock(ck, f)
  57. #define LOCK_DOWNGRADE(mxs, ck) mxs.DowngradeFromWriterLock(ck)
  58. #define LOCK_RESTORE(mxs, ck) mxs.RestoreLock(ck)
  59. #endif
  60. #define LOCK_RELEASE(mxs, ck) mxs.ReleaseLock(ck)
  61. #define ASSERT_LOCK_HELD(mxs) mxs.AssertHeld()
  62. #define ASSERT_LOCK_NOT_HELD(mxs) mxs.AssertNotHeld()
  63. #define ASSERT_LOCK_DONTCARE(mxs) // just exists to comment the code better
  64. #define ASSERT_LOCK_TAKEN_ONLY_ONCE(mxs) mxs.AssertTakenOnlyOnce()
  65. #define ASSERT_HELD_CONTINUOS_START(mxs) mxs.AssetHeldContinousStart()
  66. #define ASSERT_HELD_CONTINUOS_FINISH(mxs) mxs.AssetHeldContinousFinish()
  67. #define ASSERT_WRITE_LOCK_HELD(mxs) mxs.AssertWriterLockHeld()
  68. #define ASSERT_READ_LOCK_HELD(mxs) mxs.AssertReaderLockHeld()
  69. #define ASSERT_RORW_LOCK_HELD(mxs) mxs.AssertReaderOrWriterLockHeld()
  70. #define STATIC_LOCK(name, mxs) COleStaticLock name(mxs, __FILE__, __LINE__, #mxs)
  71. #define STATIC_WRITE_LOCK(name, mxs) CStaticWriteLock name(mxs, __FILE__, __LINE__, #mxs)
  72. #else // DBG!=1
  73. #if LOCK_PERF==1
  74. #define LOCK_WRITE(mxs) mxs.AcquireWriterLock(__FILE__, __LINE__, #mxs)
  75. #define LOCK_READ(mxs) mxs.AcquireReaderLock(__FILE__, __LINE__, #mxs)
  76. #define LOCK(mxs) mxs.Request(__FILE__, __LINE__, #mxs)
  77. #else
  78. #define LOCK_WRITE(mxs) mxs.AcquireWriterLock()
  79. #define LOCK_READ(mxs) mxs.AcquireReaderLock()
  80. #define LOCK(mxs) mxs.Request(__FILE__, __LINE__, #mxs)
  81. #endif
  82. #define UNLOCK_WRITE(mxs) mxs.ReleaseWriterLock()
  83. #define UNLOCK_READ(mxs) mxs.ReleaseReaderLock()
  84. #define UNLOCK(mxs) mxs.Release()
  85. #if LOCK_PERF==1
  86. #define LOCK_UPGRADE(mxs, ck, f) mxs.UpgradeToWriterLock(ck, f, __FILE__, __LINE__, #mxs)
  87. #define LOCK_DOWNGRADE(mxs, ck) mxs.DowngradeFromWriterLock(ck, __FILE__, __LINE__, #mxs)
  88. #define LOCK_RESTORE(mxs, ck) mxs.RestoreLock(ck, NULL, __FILE__, __LINE__, #mxs)
  89. #else
  90. #define LOCK_UPGRADE(mxs, ck, f) mxs.UpgradeToWriterLock(ck, f)
  91. #define LOCK_DOWNGRADE(mxs, ck) mxs.DowngradeFromWriterLock(ck)
  92. #define LOCK_RESTORE(mxs, ck) mxs.RestoreLock(ck)
  93. #endif
  94. #define LOCK_RELEASE(mxs, ck) mxs.ReleaseLock(ck)
  95. #define ASSERT_LOCK_HELD(mxs)
  96. #define ASSERT_LOCK_NOT_HELD(mxs)
  97. #define ASSERT_LOCK_DONTCARE(mxs)
  98. #define ASSERT_LOCK_TAKEN_ONLY_ONCE(mxs)
  99. #define ASSERT_HELD_CONTINUOS_START(mxs)
  100. #define ASSERT_HELD_CONTINUOS_FINISH(mxs)
  101. #define ASSERT_WRITE_LOCK_HELD(mxs)
  102. #define ASSERT_READ_LOCK_HELD(mxs)
  103. #define ASSERT_RORW_LOCK_HELD(mxs)
  104. #if LOCK_PERF==1
  105. #define STATIC_LOCK(name, mxs) COleStaticLock name(mxs,__FILE__, __LINE__,#mxs)
  106. #define STATIC_WRITE_LOCK(name, mxs) CStaticWriteLock name(mxs, __FILE__, __LINE__,#mxs)
  107. #else
  108. #define STATIC_LOCK(name, mxs) COleStaticLock name(mxs)
  109. #define STATIC_WRITE_LOCK(name, mxs) CStaticWriteLock name(mxs)
  110. #endif
  111. #endif // DBG!=1
  112. //
  113. // List of initialized static mutexes (which must be destroyed
  114. // during DLL exit). We know that PROCESS_ATTACH and PROCESS_DETACH
  115. // are thread-safe, so we don't protect this list with a critical section.
  116. //
  117. class COleStaticMutexSem;
  118. extern COleStaticMutexSem * g_pInitializedStaticMutexList;
  119. //
  120. // Critical section used to protect the creation of other semaphores
  121. //
  122. extern BOOL gfOleMutexCreationSemOkay;
  123. extern CRITICAL_SECTION g_OleMutexCreationSem;
  124. //
  125. // Critical section used as the backup lock when a COleStaticMutexSem
  126. // cannot be faulted in.
  127. //
  128. extern BOOL gfOleGlobalLockOkay;
  129. extern CRITICAL_SECTION g_OleGlobalLock;
  130. #if DBG
  131. //
  132. // DLL states used to ensure we don't use the wrong type of
  133. // semaphore at the wrong time
  134. //
  135. typedef enum _DLL_STATE_
  136. {
  137. DLL_STATE_STATIC_CONSTRUCTING = 0,
  138. DLL_STATE_NORMAL,
  139. DLL_STATE_PROCESS_DETACH,
  140. DLL_STATE_STATIC_DESTRUCTING,
  141. DLL_STATE_COUNT
  142. } DLL_STATE, * PDLL_STATE;
  143. //
  144. // Flag used to indicate if we're past executing the C++ constructors
  145. // during DLL initialization
  146. //
  147. extern DLL_STATE g_fDllState;
  148. #endif // DBG
  149. //+---------------------------------------------------------------------------
  150. //
  151. // Class: COleStaticMutexSem (mxs)
  152. //
  153. // Purpose: This class defines a mutual exclusion semaphore for use in
  154. // objects that are statically allocated (extern or static storage
  155. // class).
  156. //
  157. // Interface:
  158. // Request - acquire semaphore
  159. // Release - release semaphore
  160. // ReleaseFn - release semaphore (non inline version)
  161. //
  162. // History: 14-Dec-95 JeffE Initial entry.
  163. //
  164. // Notes: This class must NOT be used in dynamically allocated objects!
  165. //
  166. // This class uses the fact that static objects are initialized
  167. // by C++ to all zeroes.
  168. //
  169. //----------------------------------------------------------------------------
  170. class COleStaticMutexSem
  171. {
  172. public:
  173. COleStaticMutexSem(BOOLEAN fUseSpincount = FALSE);
  174. HRESULT Init();
  175. void Destroy();
  176. void Request(const char *pszFile, DWORD dwLine, const char *pszLockName);
  177. void Release();
  178. // debugging/diagnostic functions
  179. #if DBG==1
  180. void AssertHeld(DWORD cLocks=0);
  181. void AssertNotHeld();
  182. void AssertTakenOnlyOnce();
  183. void AssetHeldContinousStart() { _cContinuous++; }
  184. void AssetHeldContinousFinish() { Win4Assert(_cContinuous); _cContinuous--; }
  185. #else // DBG!=1
  186. inline void AssertHeld(DWORD cLocks=0) {;}
  187. inline void AssertNotHeld() {;}
  188. inline void AssertTakenOnlyOnce() {;}
  189. inline void AssetHeldContinousStart() {;}
  190. inline void AssetHeldContinousFinish() {;}
  191. #endif // DBG==1
  192. // This pointer *must* be the first member in this class
  193. class COleStaticMutexSem * pNextMutex;
  194. private:
  195. #if DBG==1 || LOCK_PERF==1
  196. // The following track lock usage for debugging purposes
  197. DWORD _dwTid; // Thread id of the thread currently holding the lock, 0 if free
  198. BOOL _fTakeOnce; // Lock is to be taken only once
  199. ULONG _cContinuous;// ensure the lock is not released while count is positive
  200. #endif // DBG==1
  201. BOOLEAN _fInitialized;// has the lock been initialized
  202. BOOLEAN _fUsingGlobal;// are we using the global lock?
  203. BOOLEAN _fAutoDestruct;
  204. BOOLEAN _fUseSpincount;
  205. DWORD _cLocks; // Number of times the thread has taken the lock
  206. DWORD _dwLine; // Line number of the code which last took the lock
  207. const char *_pszFile; // Filename of the code which last took the lock
  208. const char *_pszLockName; // Name of the lock (eg. gComLock)
  209. CRITICAL_SECTION _cs;
  210. };
  211. //+---------------------------------------------------------------------------
  212. //
  213. // Class: COleStaticLock (lck)
  214. //
  215. // Purpose: Lock using a static (or debug) Mutex Semaphore
  216. //
  217. // History: 02-Oct-91 BartoszM Created.
  218. //
  219. // Notes: Simple lock object to be created on the stack.
  220. // The constructor acquires the semaphor, the destructor
  221. // (called when lock is going out of scope) releases it.
  222. //
  223. //----------------------------------------------------------------------------
  224. class COleStaticLock
  225. {
  226. public:
  227. COleStaticLock (
  228. COleStaticMutexSem& mxs,
  229. const char * pszFile = "Unknown File",
  230. DWORD dwLine = 0L,
  231. const char *pszLockName = "Unknown Lock");
  232. ~COleStaticLock ();
  233. private:
  234. COleStaticMutexSem& _mxs;
  235. };
  236. //+---------------------------------------------------------------------------
  237. //
  238. // Class: CMutexSem2 (mxs)
  239. //
  240. // Purpose: Mutex Semaphore services. Created this version because CMutexSem will
  241. // raise exceptions. CMutexSem2 uses the Rtl* functions and will not raise
  242. // exceptions.
  243. // will not throw
  244. //
  245. // Interface: Init - initializer (two-step)
  246. // Request - acquire semaphore
  247. // Release - release semaphore
  248. //
  249. // History: 19-Mar-01 danroth Created.
  250. //
  251. // Notes: This class wraps a mutex semaphore. Mutex semaphores protect
  252. // access to resources by only allowing one client through at a
  253. // time. The client Requests the semaphore before accessing the
  254. // resource and Releases the semaphore when it is done. The
  255. // same client can Request the semaphore multiple times (a nest
  256. // count is maintained).
  257. // The mutex semaphore is a wrapper around a critical section
  258. // which does not support a timeout mechanism. Therefore the
  259. // usage of any value other than INFINITE is discouraged. It
  260. // is provided merely for compatibility.
  261. //
  262. //----------------------------------------------------------------------------
  263. class CMutexSem2
  264. {
  265. public:
  266. CMutexSem2();
  267. BOOL FInit();
  268. ~CMutexSem2();
  269. void Request();
  270. void Release();
  271. BOOL FInitialized() { return m_fCsInitialized; }
  272. private:
  273. CRITICAL_SECTION m_cs;
  274. BOOL m_fCsInitialized;
  275. };
  276. //+---------------------------------------------------------------------------
  277. //
  278. // Class: CLock2(lck)
  279. //
  280. // Purpose: Lock using a Mutex Semaphore
  281. //
  282. // History: 20-Mar-01 danroth Created.
  283. //
  284. // Notes: Simple lock object to be created on the stack.
  285. // The constructor acquires the semaphor, the destructor
  286. // (called when lock is going out of scope) releases it.
  287. //
  288. //----------------------------------------------------------------------------
  289. class CLock2
  290. {
  291. public:
  292. CLock2(CMutexSem2& mxs) : m_mxs(mxs)
  293. {
  294. m_mxs.Request();
  295. }
  296. ~CLock2() { m_mxs.Release(); }
  297. private:
  298. CMutexSem2& m_mxs;
  299. };
  300. //+---------------------------------------------------------------------------
  301. //
  302. // Member: COleStaticMutexSem::COleStaticMutexSem
  303. //
  304. // Synopsis: Debug constructor: ensure we weren't allocated dynamically.
  305. //
  306. // History: 14-Dec-1995 Jeffe
  307. //
  308. //----------------------------------------------------------------------------
  309. inline COleStaticMutexSem::COleStaticMutexSem (BOOLEAN fUseSpincount)
  310. {
  311. Win4Assert (g_fDllState == DLL_STATE_STATIC_CONSTRUCTING);
  312. _fUseSpincount = fUseSpincount;
  313. _cLocks = 0;
  314. _dwLine = 0;
  315. _pszFile = "";
  316. _pszLockName = "";
  317. #if DBG==1 || LOCK_PERF==1
  318. _dwTid = 0;
  319. _fTakeOnce = FALSE;
  320. _cContinuous = 0;
  321. #endif // DBG
  322. }
  323. //+---------------------------------------------------------------------------
  324. //
  325. // Member: COleStaticLock::COleStaticLock
  326. //
  327. // Synopsis: Acquire semaphore
  328. //
  329. // History: 02-Oct-91 BartoszM Created.
  330. //
  331. //----------------------------------------------------------------------------
  332. inline COleStaticLock::COleStaticLock ( COleStaticMutexSem& mxs, const char * pszFile, DWORD dwLine, const char *pszLockName ) : _mxs ( mxs )
  333. {
  334. _mxs.Request(pszFile, dwLine, pszLockName);
  335. }
  336. //+---------------------------------------------------------------------------
  337. //
  338. // Member: COleStaticLock::~COleStaticLock
  339. //
  340. // Synopsis: Release semaphore
  341. //
  342. // History: 02-Oct-91 BartoszM Created.
  343. //
  344. //----------------------------------------------------------------------------
  345. inline COleStaticLock::~COleStaticLock ()
  346. {
  347. _mxs.Release();
  348. }
  349. // include the reader/writer lock
  350. #include <rwlock.hxx>
  351. // Helper function to calculate spin counts for critical sections.
  352. DWORD CalculateSpinCount();
  353. #endif // _OLESEM_HXX