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.

253 lines
7.8 KiB

  1. #pragma once
  2. //
  3. // Marsthrd.h
  4. //
  5. // Classes and mechanisms for thread safety in Mars.
  6. //
  7. #include "marscom.h"
  8. //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  9. //
  10. // CRITICAL SECTION HELPER CLASSES
  11. //
  12. // There are several classes here, each with a specific purpose as follows:
  13. //
  14. // CMarsCSBase Abstract base class for a "smart crit sect" that inits itself.
  15. //
  16. // CMarsLocalCritSect A derivation of CMarsCSBase that has it's own CS -- an object
  17. // that wants to have one CritSect per instance or per class
  18. // would own one of these. NOTE: Must call _InitCS() and _TermCS()
  19. // from the owner's ctor... Use with CMarsAutoCSGrabber.
  20. //
  21. // CMarsGlobalCritSect A derivation of CMarsCSBase that has a single crit sect for
  22. // the entire application. This is a static accessor class, so
  23. // one instance of the class should be created by each client wanting
  24. // access to the global crit sect. Use with CMarsAutoCSGrabber.
  25. //
  26. // CMarsAutoCSGrabber Smart object that "grabs" the crit sect and holds it for its
  27. // scoped lifetime. Drop this at the begining of a scope block
  28. // (constructed with a reference to the correct CMarsCSBase) and
  29. // you're protected. Default parameter fAutoEnter on the ctor
  30. // allows you to not enter the CS by default. This object tracks
  31. // the status of its paired calls to Enter/Leave so you can call
  32. // Leave and then Re-enter and the correct thing will happen.
  33. //
  34. // CMarsGlobalCSGrabber A derivation of CMarsAutoCSGrabber that makes grabbing the
  35. // global CS even easier by rolling the CMarsAutoCSGrabber together
  36. // with an instance of CMarsGlobalCritSect.
  37. //
  38. //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  39. //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  40. // class CMarsCSBase
  41. //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  42. class CMarsCSBase
  43. {
  44. public:
  45. CMarsCSBase() {}
  46. virtual ~CMarsCSBase() {}
  47. virtual void _CSInit()
  48. {
  49. InitializeCriticalSection(GetCS());
  50. }
  51. virtual void _CSTerm() { DeleteCriticalSection(GetCS()); }
  52. void Enter(void)
  53. {
  54. EnterCriticalSection(GetCS());
  55. }
  56. void Leave(void)
  57. {
  58. LeaveCriticalSection(GetCS());
  59. }
  60. protected:
  61. virtual CRITICAL_SECTION *GetCS(void) = 0;
  62. }; // CMarsCSBase
  63. //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  64. // class CMarsGlobalCritSect
  65. //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  66. class CMarsGlobalCritSect : public CMarsCSBase
  67. {
  68. public:
  69. CMarsGlobalCritSect() {}
  70. virtual ~CMarsGlobalCritSect() {}
  71. static void InitializeCritSect(void) { InitializeCriticalSection(&m_CS); }
  72. static void TerminateCritSect(void) { DeleteCriticalSection(&m_CS); }
  73. private:
  74. // Make these private and re-expose public static methods that initialize and terminate only
  75. // once per process
  76. virtual void _CSInit() { return; }
  77. virtual void _CSTerm() { return; }
  78. virtual CRITICAL_SECTION *GetCS(void) { return &m_CS; }
  79. static CRITICAL_SECTION m_CS;
  80. }; // CMarsGlobalCritSect
  81. //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  82. // class CMarsAutoCSGrabber
  83. //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  84. class CMarsAutoCSGrabber
  85. {
  86. public:
  87. CMarsAutoCSGrabber(CMarsCSBase *pCS, bool fAutoEnter = true)
  88. : m_fIsIn(false),
  89. m_pCS(pCS)
  90. {
  91. if (fAutoEnter)
  92. Enter();
  93. }
  94. ~CMarsAutoCSGrabber()
  95. {
  96. Leave();
  97. }
  98. void Enter(void)
  99. {
  100. ATLASSERT((NULL != m_pCS));
  101. if (!m_fIsIn && (NULL != m_pCS))
  102. {
  103. m_pCS->Enter();
  104. m_fIsIn = true;
  105. }
  106. }
  107. void Leave(void)
  108. {
  109. ATLASSERT(NULL != m_pCS);
  110. if (m_fIsIn && (NULL != m_pCS))
  111. {
  112. m_fIsIn = false;
  113. m_pCS->Leave();
  114. }
  115. }
  116. protected:
  117. // Hide this and delcare with defining so if anybody uses it, the compiler barfs.
  118. CMarsAutoCSGrabber();
  119. protected:
  120. bool m_fIsIn;
  121. CMarsCSBase *m_pCS;
  122. }; // CMarsAutoCSGrabber
  123. //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  124. // class CMarsGlobalCSGrabber
  125. //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  126. class CMarsGlobalCSGrabber
  127. {
  128. public:
  129. // Need to not allow the base ctor to do AutoEnter because it'll fail since the
  130. // m_CS object's ctor hasn't run yet when the CMarsAutoCSGrabber ctor is called.
  131. CMarsGlobalCSGrabber(bool fAutoEnter = true) : m_grabber(&m_CS, false)
  132. {
  133. if (fAutoEnter)
  134. Enter();
  135. }
  136. ~CMarsGlobalCSGrabber()
  137. {
  138. Leave();
  139. }
  140. void Enter(void) { m_grabber.Enter(); }
  141. void Leave(void) { m_grabber.Leave(); }
  142. private:
  143. CMarsGlobalCritSect m_CS;
  144. CMarsAutoCSGrabber m_grabber;
  145. }; // CMarsGlobalCSGrabber
  146. //---------------------------------------------------------------------------------
  147. // CMarsComObjectThreadSafe provides some functionality used by a few Mars COM objects
  148. // that need to be thread-safe including addref/release and passivation
  149. // Exposed methods should be protected to ensure that they're not called while the
  150. // object is passive. There are three types of passivation protection:
  151. // if (VerifyNotPassive()) - this function should not be called while passive,
  152. // but we still want to protect against it
  153. // if (IsPassive()) - this function may be called while passive,
  154. // but we want to protect against it
  155. // ASSERT(!IsPassive()); - we're pretty sure this won't be called while passive,
  156. // but we want to detect it if it starts happening
  157. // Use:
  158. // derive from CMarsComObjectThreadSafe
  159. // IMPLEMENT_ADDREF_RELEASE in source file
  160. // Implement DoPassivate()
  161. // Implement GetCS() to return a CMarsCSBase * (your own or the global one, as appropriate)
  162. // Use IsPassive() and VerifyNotPassive() where appropriate
  163. // Don't call "delete" directly
  164. // CYourClass->Passivate() should be called before CYourClass->Release()
  165. //
  166. class CMarsComObjectThreadSafe : protected CMarsComObject
  167. {
  168. public:
  169. BOOL IsPassive()
  170. {
  171. CMarsAutoCSGrabber cs(GetCS());
  172. return CMarsComObject::IsPassive();
  173. }
  174. virtual HRESULT Passivate()
  175. {
  176. CMarsAutoCSGrabber cs(GetCS());
  177. return CMarsComObject::Passivate();
  178. }
  179. protected:
  180. CMarsComObjectThreadSafe()
  181. {
  182. }
  183. virtual ~CMarsComObjectThreadSafe() { }
  184. ULONG InternalAddRef()
  185. {
  186. return InterlockedIncrement(&m_cRef);
  187. }
  188. ULONG InternalRelease()
  189. {
  190. if (InterlockedDecrement(&m_cRef))
  191. {
  192. return m_cRef;
  193. }
  194. delete this;
  195. return 0;
  196. }
  197. inline BOOL VerifyNotPassive(HRESULT *phr=NULL)
  198. {
  199. CMarsAutoCSGrabber cs(GetCS());
  200. return CMarsComObject::VerifyNotPassive(phr);
  201. }
  202. virtual HRESULT DoPassivate() = 0;
  203. virtual CMarsCSBase *GetCS() = 0;
  204. }; // CMarsComObjectThreadSafe