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.

328 lines
5.8 KiB

  1. // -*- C++ -*-
  2. // Copyright (C) 2009-2010, Vaclav Haisman. All rights reserved.
  3. //
  4. // Redistribution and use in source and binary forms, with or without modifica-
  5. // tion, are permitted provided that the following conditions are met:
  6. //
  7. // 1. Redistributions of source code must retain the above copyright notice,
  8. // this list of conditions and the following disclaimer.
  9. //
  10. // 2. Redistributions in binary form must reproduce the above copyright notice,
  11. // this list of conditions and the following disclaimer in the documentation
  12. // and/or other materials provided with the distribution.
  13. //
  14. // THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  15. // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  16. // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  17. // APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  18. // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
  19. // DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  20. // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  21. // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23. // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. //! @file
  25. //! This file contains implementations of synchronization
  26. //! primitives using the Win32 API. It does not contain any include
  27. //! guards because it is only a fragment to be included by
  28. //! syncprims.h.
  29. #include <stdexcept>
  30. namespace log4cplus { namespace thread { namespace impl {
  31. //
  32. //
  33. //
  34. inline
  35. bool
  36. InitializeCriticalSection_wrapInternal (LPCRITICAL_SECTION cs)
  37. {
  38. #if defined (_MSC_VER)
  39. __try
  40. {
  41. #endif
  42. InitializeCriticalSection (cs);
  43. #if defined (_MSC_VER)
  44. }
  45. __except (GetExceptionCode() == STATUS_NO_MEMORY
  46. ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  47. {
  48. return false;
  49. }
  50. #endif
  51. return true;
  52. }
  53. inline
  54. void
  55. InitializeCriticalSection_wrap (LPCRITICAL_SECTION cs)
  56. {
  57. if (! InitializeCriticalSection_wrapInternal (cs))
  58. throw std::runtime_error (
  59. "InitializeCriticalSection: STATUS_NO_MEMORY");
  60. }
  61. inline
  62. Mutex::Mutex (log4cplus::thread::Mutex::Type)
  63. {
  64. InitializeCriticalSection_wrap (&cs);
  65. }
  66. inline
  67. Mutex::~Mutex ()
  68. {
  69. DeleteCriticalSection (&cs);
  70. }
  71. inline
  72. void
  73. Mutex::lock () const
  74. {
  75. EnterCriticalSection (&cs);
  76. }
  77. inline
  78. void
  79. Mutex::unlock () const
  80. {
  81. LeaveCriticalSection (&cs);
  82. }
  83. //
  84. //
  85. //
  86. inline
  87. Semaphore::Semaphore (unsigned max, unsigned initial)
  88. {
  89. sem = CreateSemaphore (0, initial, max, 0);
  90. if (! sem)
  91. LOG4CPLUS_THROW_RTE ("Semaphore::Semaphore");
  92. }
  93. inline
  94. Semaphore::~Semaphore ()
  95. {
  96. try
  97. {
  98. if (! CloseHandle (sem))
  99. LOG4CPLUS_THROW_RTE ("Semaphore::~Semaphore");
  100. }
  101. catch (...)
  102. { }
  103. }
  104. inline
  105. void
  106. Semaphore::unlock () const
  107. {
  108. DWORD ret = ReleaseSemaphore (sem, 1, 0);
  109. if (! ret)
  110. LOG4CPLUS_THROW_RTE ("Semaphore::unlock");
  111. }
  112. inline
  113. void
  114. Semaphore::lock () const
  115. {
  116. DWORD ret = WaitForSingleObject (sem, INFINITE);
  117. if (ret != WAIT_OBJECT_0)
  118. LOG4CPLUS_THROW_RTE ("Semaphore::lock");
  119. }
  120. //
  121. //
  122. //
  123. inline
  124. FairMutex::FairMutex ()
  125. {
  126. mtx = CreateMutex (0, false, 0);
  127. if (! mtx)
  128. LOG4CPLUS_THROW_RTE ("FairMutex::FairMutex");
  129. }
  130. inline
  131. FairMutex::~FairMutex ()
  132. {
  133. try
  134. {
  135. if (! CloseHandle (mtx))
  136. LOG4CPLUS_THROW_RTE ("FairMutex::~FairMutex");
  137. }
  138. catch (...)
  139. { }
  140. }
  141. inline
  142. void
  143. FairMutex::lock () const
  144. {
  145. DWORD ret = WaitForSingleObject (mtx, INFINITE);
  146. if (ret != WAIT_OBJECT_0)
  147. LOG4CPLUS_THROW_RTE ("FairMutex::lock");
  148. }
  149. inline
  150. void
  151. FairMutex::unlock () const
  152. {
  153. if (! ReleaseMutex (mtx))
  154. LOG4CPLUS_THROW_RTE ("FairMutex::unlock");
  155. }
  156. //
  157. //
  158. //
  159. inline
  160. ManualResetEvent::ManualResetEvent (bool sig)
  161. {
  162. ev = CreateEvent (0, true, sig, 0);
  163. if (! ev)
  164. LOG4CPLUS_THROW_RTE ("ManualResetEvent::ManualResetEvent");
  165. }
  166. inline
  167. ManualResetEvent::~ManualResetEvent ()
  168. {
  169. try
  170. {
  171. if (! CloseHandle (ev))
  172. LOG4CPLUS_THROW_RTE ("ManualResetEvent::~ManualResetEvent");
  173. }
  174. catch (...)
  175. { }
  176. }
  177. inline
  178. void
  179. ManualResetEvent::signal () const
  180. {
  181. if (! SetEvent (ev))
  182. LOG4CPLUS_THROW_RTE ("ManualResetEVent::signal");
  183. }
  184. inline
  185. void
  186. ManualResetEvent::wait () const
  187. {
  188. DWORD ret = WaitForSingleObject (ev, INFINITE);
  189. if (ret != WAIT_OBJECT_0)
  190. LOG4CPLUS_THROW_RTE ("ManualResetEvent::wait");
  191. }
  192. inline
  193. bool
  194. ManualResetEvent::timed_wait (unsigned long msec) const
  195. {
  196. DWORD ret = WaitForSingleObject (ev, static_cast<DWORD>(msec));
  197. switch(ret)
  198. {
  199. case WAIT_OBJECT_0:
  200. return true;
  201. case WAIT_TIMEOUT:
  202. return false;
  203. default:
  204. LOG4CPLUS_THROW_RTE ("ManualResetEvent::timed_wait");
  205. // Silence warnings about not returning any value from function
  206. // returning bool.
  207. return false;
  208. }
  209. }
  210. inline
  211. void
  212. ManualResetEvent::reset () const
  213. {
  214. if (! ResetEvent (ev))
  215. LOG4CPLUS_THROW_RTE ("ManualResetEvent::reset");
  216. }
  217. //
  218. //
  219. //
  220. #if defined (LOG4CPLUS_POOR_MANS_SHAREDMUTEX)
  221. #include "log4cplus/thread/impl/syncprims-pmsm.h"
  222. #else
  223. inline
  224. SharedMutex::SharedMutex ()
  225. {
  226. InitializeSRWLock (&srwl);
  227. }
  228. inline
  229. SharedMutex::~SharedMutex ()
  230. { }
  231. inline
  232. void
  233. SharedMutex::rdlock () const
  234. {
  235. AcquireSRWLockShared (&srwl);
  236. }
  237. inline
  238. void
  239. SharedMutex::rdunlock () const
  240. {
  241. ReleaseSRWLockShared (&srwl);
  242. }
  243. inline
  244. void
  245. SharedMutex::wrlock () const
  246. {
  247. AcquireSRWLockExclusive (&srwl);
  248. }
  249. inline
  250. void
  251. SharedMutex::wrunlock () const
  252. {
  253. ReleaseSRWLockExclusive (&srwl);
  254. }
  255. #endif
  256. } } } // namespace log4cplus { namespace thread { namespace impl {