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.

140 lines
4.7 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // INTEL Corporation Proprietary Information
  3. // This listing is supplied under the terms of a license agreement with Intel
  4. // Corporation and many not be copied nor disclosed except in accordance
  5. // with the terms of that agreement.
  6. // Copyright (c) 1995, 1996 Intel Corporation.
  7. //
  8. //
  9. // Module Name: thrdsafe.h
  10. // Abstract: Defines thread-safety utility classes and macros.
  11. // Environment: MSVC 4.0, OLE 2
  12. /////////////////////////////////////////////////////////////////////////////////
  13. // $Header: R:/rtp/src/ppm/THRDSAFE.H_v 1.4 31 Jan 1997 23:32:36 CPEARSON $
  14. #ifndef __THRDSAFE_H__
  15. #define __THRDSAFE_H__
  16. #include <winbase.h> // CRITICAL_SECTION
  17. ////////////////////////////////////////////////////////////////////////
  18. // Helper macros for using class CSerialBlockGuard. On entry to a
  19. // serialized statement block, code:
  20. //
  21. // SERIALIZEDBLOCKENTRY(myCriticalSection);
  22. //
  23. // The macro will return only after ownership of the myCriticalSection is
  24. // obtained. The CSerialBlockGuard destructor will exit the critical
  25. // section when control leaves the block. Because it declares an automatic
  26. // variable, you can only use SERIALIZEDBLOCKENTRY() once in a block.
  27. //
  28. // In cases where you wish to exit the critical section while still in
  29. // the block, code:
  30. //
  31. // SERIALIZEDBLOCKEARLYEXIT();
  32. //
  33. // If you need to exit and re-enter the critical section in the same
  34. // block, then these macros won't buy you anything -- just manipulate
  35. // the critical section directly.
  36. #define SERIALIZEDBLOCKENTRY(CS) CSerialBlockGuard serialBlockGuard(&(CS))
  37. #define SERIALIZEDBLOCKEARLYEXIT() serialBlockGuard.EarlyExit()
  38. ////////////////////////////////////////////////////////////////////////
  39. // class CSerialBlockGuard: Helper class to manage critical section
  40. // on entry/exit of serialized code blocks (typically functions).
  41. // On construction, objects of this class block the given critical
  42. // section, and release the c.s. on destruction, ensuring proper cleanup
  43. // for all exit routes.
  44. class CSerialBlockGuard
  45. {
  46. LPCRITICAL_SECTION m_pCritSect;
  47. public:
  48. CSerialBlockGuard(CRITICAL_SECTION* pCritSect) :
  49. m_pCritSect(pCritSect)
  50. { EnterCriticalSection(m_pCritSect); }
  51. CSerialBlockGuard(const CSerialBlockGuard& rOriginal) :
  52. m_pCritSect(rOriginal.m_pCritSect) {;}
  53. void EarlyExit()
  54. { if (m_pCritSect) LeaveCriticalSection(m_pCritSect); m_pCritSect = NULL; }
  55. ~CSerialBlockGuard()
  56. { if (m_pCritSect) LeaveCriticalSection(m_pCritSect); }
  57. };
  58. ////////////////////////////////////////////////////////////////////////
  59. // Helper macros for coding class CThreadSafe serialized methods. To
  60. // ensure that entry to a method is serialized across threads, code:
  61. //
  62. // THREADSAFEENTRY();
  63. //
  64. // before accessing shared member variables. The macro will return
  65. // only after ownership of this->m_critSect is obtained.
  66. //
  67. // In cases where you wish to exit the critical section while still in
  68. // the method, code:
  69. //
  70. // THREADSAFEEARLYEXIT();
  71. //
  72. // If you need to exit and re-enter the critical section in the same
  73. // method, then use the CThreadSafe::Lock() and CThreadSafe::Unlock()
  74. // methods instead.
  75. #define THREADSAFEENTRY() SERIALIZEDBLOCKENTRY(*getCritSect())
  76. #define THREADSAFEEARLYEXIT() SERIALIZEDBLOCKEARLYEXIT()
  77. ////////////////////////////////////////////////////////////////////////
  78. // class CThreadSafe: A minimal base class from which to derive
  79. // thread-safe classes. These classes serialize entry to methods using
  80. // the THREADSAFEENTRY() macro. Derived class should declare this a
  81. // protected base to hide serialization methods. For derived classes
  82. // with multiple base classes, if serialization is needed during
  83. // construction (unusual), this should be first base class, and should
  84. // be constructed with bInitialLock == TRUE;
  85. class CThreadSafe
  86. {
  87. CRITICAL_SECTION m_critSect;
  88. // Hide assignment operator, forcing compiler to use copy ctor.
  89. CThreadSafe& operator=(const CThreadSafe&);
  90. public:
  91. CThreadSafe(BOOL bInitialLock = FALSE)
  92. { InitializeCriticalSection(&m_critSect); if (bInitialLock) Lock(); }
  93. // Copy ctor creates a new critical section, but doesn't lock, on
  94. // assumption that new object can't yet be visible to another thread.
  95. CThreadSafe(const CThreadSafe& rOriginal)
  96. { InitializeCriticalSection(&m_critSect); }
  97. ~CThreadSafe()
  98. { DeleteCriticalSection(&m_critSect); }
  99. // Castaway const in following methods, so that const methods can
  100. // access members in a thread-safe manner.
  101. void Lock() const
  102. { EnterCriticalSection((LPCRITICAL_SECTION) &m_critSect); }
  103. void Unlock() const
  104. { LeaveCriticalSection((LPCRITICAL_SECTION) &m_critSect); }
  105. protected:
  106. LPCRITICAL_SECTION getCritSect() const
  107. { return (LPCRITICAL_SECTION) &m_critSect; }
  108. };
  109. #endif // __THRDSAFE_H__