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.

306 lines
9.5 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/synch/thread_mutex.hpp
  3. *
  4. * Purpose: Intra-process mutex, based on Windows CRITICAL_SECTION.
  5. *
  6. * Created: 17th December 1996
  7. * Updated: 10th August 2009
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 1996-2009, Matthew Wilson and Synesis Software
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright notice, this
  18. * list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  23. * any contributors may be used to endorse or promote products derived from
  24. * this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * ////////////////////////////////////////////////////////////////////// */
  39. /** \file winstl/synch/thread_mutex.hpp
  40. *
  41. * \brief [C++ only] Definition of winstl::thread_mutex class
  42. * (\ref group__library__synch "Synchronisation" Library).
  43. */
  44. #ifndef WINSTL_INCL_WINSTL_SYNCH_HPP_THREAD_MUTEX
  45. #define WINSTL_INCL_WINSTL_SYNCH_HPP_THREAD_MUTEX
  46. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  47. # define WINSTL_VER_WINSTL_SYNCH_HPP_THREAD_MUTEX_MAJOR 4
  48. # define WINSTL_VER_WINSTL_SYNCH_HPP_THREAD_MUTEX_MINOR 0
  49. # define WINSTL_VER_WINSTL_SYNCH_HPP_THREAD_MUTEX_REVISION 1
  50. # define WINSTL_VER_WINSTL_SYNCH_HPP_THREAD_MUTEX_EDIT 52
  51. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  52. /* /////////////////////////////////////////////////////////////////////////
  53. * Includes
  54. */
  55. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  56. # include <winstl/winstl.h>
  57. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  58. #ifndef STLSOFT_INCL_STLSOFT_SYNCH_HPP_CONCEPTS
  59. # include <stlsoft/synch/concepts.hpp>
  60. #endif /* !STLSOFT_INCL_STLSOFT_SYNCH_HPP_CONCEPTS */
  61. /* /////////////////////////////////////////////////////////////////////////
  62. * Namespace
  63. */
  64. #ifndef _WINSTL_NO_NAMESPACE
  65. # if defined(_STLSOFT_NO_NAMESPACE) || \
  66. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  67. /* There is no stlsoft namespace, so must define ::winstl */
  68. namespace winstl
  69. {
  70. # else
  71. /* Define stlsoft::winstl_project */
  72. namespace stlsoft
  73. {
  74. namespace winstl_project
  75. {
  76. # endif /* _STLSOFT_NO_NAMESPACE */
  77. #endif /* !_WINSTL_NO_NAMESPACE */
  78. /* /////////////////////////////////////////////////////////////////////////
  79. * Spin-count support
  80. */
  81. #ifdef __WINSTL_THREAD_MUTEX_SPIN_COUNT_SUPPORT
  82. # undef __WINSTL_THREAD_MUTEX_SPIN_COUNT_SUPPORT
  83. #endif /* __WINSTL_THREAD_MUTEX_SPIN_COUNT_SUPPORT */
  84. #ifdef __WINSTL_THREAD_MUTEX_TRY_LOCK_SUPPORT
  85. # undef __WINSTL_THREAD_MUTEX_TRY_LOCK_SUPPORT
  86. #endif /* __WINSTL_THREAD_MUTEX_TRY_LOCK_SUPPORT */
  87. #if defined(_WIN32_WINNT) && \
  88. _WIN32_WINNT >= 0x0403
  89. # define __WINSTL_THREAD_MUTEX_SPIN_COUNT_SUPPORT
  90. #endif /* _WIN32_WINNT >= 0x0403 */
  91. #if defined(_WIN32_WINNT) && \
  92. _WIN32_WINNT >= 0x0400
  93. # define __WINSTL_THREAD_MUTEX_TRY_LOCK_SUPPORT
  94. #endif /* _WIN32_WINNT >= 0x0400 */
  95. /* /////////////////////////////////////////////////////////////////////////
  96. * Classes
  97. */
  98. // class thread_mutex
  99. /** \brief This class provides an implementation of the mutex model based on the Win32 CRITICAL_SECTION
  100. *
  101. * \ingroup group__library__synch
  102. */
  103. class thread_mutex
  104. : public stlsoft_ns_qual(critical_section)< STLSOFT_CRITICAL_SECTION_IS_RECURSIVE
  105. #ifdef __WINSTL_THREAD_MUTEX_TRY_LOCK_SUPPORT
  106. , STLSOFT_CRITICAL_SECTION_IS_TRYABLE
  107. #else /* ? __WINSTL_THREAD_MUTEX_TRY_LOCK_SUPPORT */
  108. , STLSOFT_CRITICAL_SECTION_ISNOT_TRYABLE
  109. #endif /* __WINSTL_THREAD_MUTEX_TRY_LOCK_SUPPORT */
  110. >
  111. {
  112. public:
  113. /// This type
  114. typedef thread_mutex class_type;
  115. // Construction
  116. public:
  117. /// Creates an instance of the mutex
  118. thread_mutex() stlsoft_throw_0()
  119. {
  120. ::InitializeCriticalSection(&m_cs);
  121. }
  122. #if defined(__WINSTL_THREAD_MUTEX_SPIN_COUNT_SUPPORT)
  123. /// Creates an instance of the mutex and sets its spin count
  124. ///
  125. /// \param spinCount The new spin count for the mutex
  126. /// \note Only available with Windows NT 4 SP3 and later
  127. thread_mutex(ws_dword_t spinCount) stlsoft_throw_0()
  128. {
  129. ::InitializeCriticalSectionAndSpinCount(&m_cs, spinCount);
  130. }
  131. #endif /* __WINSTL_THREAD_MUTEX_SPIN_COUNT_SUPPORT */
  132. /// Destroys an instance of the mutex
  133. ~thread_mutex() stlsoft_throw_0()
  134. {
  135. ::DeleteCriticalSection(&m_cs);
  136. }
  137. // Operations
  138. public:
  139. /// Acquires a lock on the mutex, pending the thread until the lock is aquired
  140. void lock() stlsoft_throw_0()
  141. {
  142. ::EnterCriticalSection(&m_cs);
  143. }
  144. #if defined(__WINSTL_THREAD_MUTEX_TRY_LOCK_SUPPORT)
  145. /// Attempts to lock the mutex
  146. ///
  147. /// \return <b>true</b> if the mutex was aquired, or <b>false</b> if not
  148. /// \note Only available with Windows NT 4 and later
  149. bool try_lock()
  150. {
  151. return ::TryEnterCriticalSection(&m_cs) != FALSE;
  152. }
  153. #endif /* __WINSTL_THREAD_MUTEX_TRY_LOCK_SUPPORT */
  154. /// Releases an aquired lock on the mutex
  155. void unlock() stlsoft_throw_0()
  156. {
  157. ::LeaveCriticalSection(&m_cs);
  158. }
  159. #if defined(__WINSTL_THREAD_MUTEX_SPIN_COUNT_SUPPORT)
  160. /// Sets the spin count for the mutex
  161. ///
  162. /// \param spinCount The new spin count for the mutex
  163. /// \return The previous spin count associated with the mutex
  164. /// \note Only available with Windows NT 4 SP3 and later
  165. ws_dword_t set_spin_count(ws_dword_t spinCount) stlsoft_throw_0()
  166. {
  167. return ::SetCriticalSectionSpinCount(&m_cs, spinCount);
  168. }
  169. #endif /* __WINSTL_THREAD_MUTEX_SPIN_COUNT_SUPPORT */
  170. // Members
  171. private:
  172. CRITICAL_SECTION m_cs; // critical section
  173. // Not to be implemented
  174. private:
  175. thread_mutex(class_type const& rhs);
  176. thread_mutex& operator =(class_type const& rhs);
  177. };
  178. /* /////////////////////////////////////////////////////////////////////////
  179. * Control shims
  180. */
  181. #ifndef _WINSTL_NO_NAMESPACE
  182. # if defined(_STLSOFT_NO_NAMESPACE) || \
  183. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  184. } // namespace winstl
  185. # else
  186. } // namespace winstl_project
  187. # endif /* _STLSOFT_NO_NAMESPACE */
  188. #endif /* !_WINSTL_NO_NAMESPACE */
  189. /** \brief This \ref group__concept__shims "control shim" aquires a lock on the given mutex
  190. *
  191. * \ingroup group__concept__shim__synchronisation_control
  192. *
  193. * \param mx The mutex on which to aquire the lock.
  194. */
  195. inline void lock_instance(winstl_ns_qual(thread_mutex) &mx)
  196. {
  197. mx.lock();
  198. }
  199. /** \brief This \ref group__concept__shims "control shim" releases a lock on the given mutex
  200. *
  201. * \ingroup group__concept__shim__synchronisation_control
  202. *
  203. * \param mx The mutex on which to release the lock
  204. */
  205. inline void unlock_instance(winstl_ns_qual(thread_mutex) &mx)
  206. {
  207. mx.unlock();
  208. }
  209. #ifndef _WINSTL_NO_NAMESPACE
  210. # if defined(_STLSOFT_NO_NAMESPACE) || \
  211. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  212. namespace winstl {
  213. # else
  214. namespace winstl_project {
  215. # if defined(STLSOFT_COMPILER_IS_BORLAND)
  216. using ::stlsoft::lock_instance;
  217. using ::stlsoft::unlock_instance;
  218. # endif /* compiler */
  219. # endif /* _STLSOFT_NO_NAMESPACE */
  220. #endif /* !_WINSTL_NO_NAMESPACE */
  221. /* /////////////////////////////////////////////////////////////////////////
  222. * lock_traits
  223. */
  224. // class lock_traits
  225. /** \brief Traits for the thread_mutex class
  226. *
  227. * \ingroup group__library__synch
  228. */
  229. struct thread_mutex_lock_traits
  230. {
  231. public:
  232. /// The lockable type
  233. typedef thread_mutex lock_type;
  234. /// This type
  235. typedef thread_mutex_lock_traits class_type;
  236. // Operations
  237. public:
  238. /// Lock the given thread_mutex instance
  239. static void lock(thread_mutex &c)
  240. {
  241. lock_instance(c);
  242. }
  243. /// Unlock the given thread_mutex instance
  244. static void unlock(thread_mutex &c)
  245. {
  246. unlock_instance(c);
  247. }
  248. };
  249. ////////////////////////////////////////////////////////////////////////////
  250. // Unit-testing
  251. #ifdef STLSOFT_UNITTEST
  252. # include "./unittest/thread_mutex_unittest_.h"
  253. #endif /* STLSOFT_UNITTEST */
  254. /* ////////////////////////////////////////////////////////////////////// */
  255. #ifndef _WINSTL_NO_NAMESPACE
  256. # if defined(_STLSOFT_NO_NAMESPACE) || \
  257. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  258. } // namespace winstl
  259. # else
  260. } // namespace winstl_project
  261. } // namespace stlsoft
  262. # endif /* _STLSOFT_NO_NAMESPACE */
  263. #endif /* !_WINSTL_NO_NAMESPACE */
  264. /* ////////////////////////////////////////////////////////////////////// */
  265. #endif /* !WINSTL_INCL_WINSTL_SYNCH_HPP_THREAD_MUTEX */
  266. /* ///////////////////////////// end of file //////////////////////////// */