syncprims.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. // -*- C++ -*-
  2. // Copyright (C) 2010-2017, 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. #ifndef LOG4CPLUS_THREAD_SYNCPRIMS_H
  25. #define LOG4CPLUS_THREAD_SYNCPRIMS_H
  26. #include <log4cplus/config.hxx>
  27. #if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
  28. #pragma once
  29. #endif
  30. #include <mutex>
  31. #include <condition_variable>
  32. namespace log4cplus { namespace thread {
  33. template <typename SyncPrim>
  34. class SyncGuard
  35. {
  36. public:
  37. SyncGuard ();
  38. SyncGuard (SyncPrim const &);
  39. ~SyncGuard ();
  40. SyncGuard (SyncGuard const &) = delete;
  41. SyncGuard & operator = (SyncGuard const &) = delete;
  42. void lock ();
  43. void unlock ();
  44. void attach (SyncPrim const &);
  45. void attach_and_lock (SyncPrim const &);
  46. void detach ();
  47. private:
  48. SyncPrim const * sp;
  49. };
  50. class LOG4CPLUS_EXPORT SimpleMutex
  51. {
  52. public:
  53. SimpleMutex ();
  54. ~SimpleMutex ();
  55. SimpleMutex (SimpleMutex const &) = delete;
  56. SimpleMutex & operator = (SimpleMutex const &) = delete;
  57. void lock () const;
  58. bool try_lock () const;
  59. void unlock () const;
  60. private:
  61. LOG4CPLUS_THREADED (mutable std::mutex mtx;)
  62. };
  63. typedef SyncGuard<SimpleMutex> SimpleMutexGuard;
  64. class LOG4CPLUS_EXPORT Mutex
  65. {
  66. public:
  67. Mutex ();
  68. ~Mutex ();
  69. Mutex (Mutex const &) = delete;
  70. Mutex & operator = (Mutex const &) = delete;
  71. void lock () const;
  72. void unlock () const;
  73. private:
  74. LOG4CPLUS_THREADED (mutable std::recursive_mutex mtx;)
  75. };
  76. typedef SyncGuard<Mutex> MutexGuard;
  77. class LOG4CPLUS_EXPORT Semaphore
  78. {
  79. public:
  80. Semaphore (unsigned max, unsigned initial);
  81. ~Semaphore ();
  82. Semaphore (Semaphore const &) = delete;
  83. Semaphore & operator = (Semaphore const &) = delete;
  84. void lock () const;
  85. void unlock () const;
  86. private:
  87. #if ! defined (LOG4CPLUS_SINGLE_THREADED)
  88. mutable std::mutex mtx;
  89. mutable std::condition_variable cv;
  90. mutable unsigned maximum;
  91. mutable unsigned val;
  92. #endif
  93. };
  94. typedef SyncGuard<Semaphore> SemaphoreGuard;
  95. class LOG4CPLUS_EXPORT ManualResetEvent
  96. {
  97. public:
  98. explicit ManualResetEvent (bool = false);
  99. ~ManualResetEvent ();
  100. ManualResetEvent (ManualResetEvent const &) = delete;
  101. ManualResetEvent & operator = (ManualResetEvent const &) = delete;
  102. void signal () const;
  103. void wait () const;
  104. bool timed_wait (unsigned long msec) const;
  105. void reset () const;
  106. private:
  107. #if ! defined (LOG4CPLUS_SINGLE_THREADED)
  108. mutable std::mutex mtx;
  109. mutable std::condition_variable cv;
  110. mutable bool signaled;
  111. mutable unsigned sigcount;
  112. #endif
  113. };
  114. class SharedMutexImplBase
  115. {
  116. protected:
  117. ~SharedMutexImplBase ();
  118. };
  119. template <typename SyncPrim, void (SyncPrim:: * lock_func) () const,
  120. void (SyncPrim:: * unlock_func) () const>
  121. class SyncGuardFunc
  122. {
  123. public:
  124. SyncGuardFunc (SyncPrim const &);
  125. ~SyncGuardFunc ();
  126. void lock ();
  127. void unlock ();
  128. void attach (SyncPrim const &);
  129. void detach ();
  130. private:
  131. SyncPrim const * sp;
  132. SyncGuardFunc (SyncGuardFunc const &);
  133. SyncGuardFunc & operator = (SyncGuardFunc const &);
  134. };
  135. class LOG4CPLUS_EXPORT SharedMutex
  136. {
  137. public:
  138. SharedMutex ();
  139. ~SharedMutex ();
  140. void rdlock () const;
  141. void rdunlock () const;
  142. void wrlock () const;
  143. void wrunlock () const;
  144. private:
  145. SharedMutexImplBase * sm;
  146. SharedMutex (SharedMutex const &);
  147. SharedMutex & operator = (SharedMutex const &);
  148. };
  149. typedef SyncGuardFunc<SharedMutex, &SharedMutex::rdlock,
  150. &SharedMutex::rdunlock> SharedMutexReaderGuard;
  151. typedef SyncGuardFunc<SharedMutex, &SharedMutex::wrlock,
  152. &SharedMutex::wrunlock> SharedMutexWriterGuard;
  153. //
  154. //
  155. //
  156. template <typename SyncPrim>
  157. inline
  158. SyncGuard<SyncPrim>::SyncGuard ()
  159. : sp (0)
  160. { }
  161. template <typename SyncPrim>
  162. inline
  163. SyncGuard<SyncPrim>::SyncGuard (SyncPrim const & m)
  164. : sp (&m)
  165. {
  166. sp->lock ();
  167. }
  168. template <typename SyncPrim>
  169. inline
  170. SyncGuard<SyncPrim>::~SyncGuard ()
  171. {
  172. if (sp)
  173. sp->unlock ();
  174. }
  175. template <typename SyncPrim>
  176. inline
  177. void
  178. SyncGuard<SyncPrim>::lock ()
  179. {
  180. sp->lock ();
  181. }
  182. template <typename SyncPrim>
  183. inline
  184. void
  185. SyncGuard<SyncPrim>::unlock ()
  186. {
  187. sp->unlock ();
  188. }
  189. template <typename SyncPrim>
  190. inline
  191. void
  192. SyncGuard<SyncPrim>::attach (SyncPrim const & m)
  193. {
  194. sp = &m;
  195. }
  196. template <typename SyncPrim>
  197. inline
  198. void
  199. SyncGuard<SyncPrim>::attach_and_lock (SyncPrim const & m)
  200. {
  201. attach (m);
  202. try
  203. {
  204. lock();
  205. }
  206. catch (...)
  207. {
  208. detach ();
  209. throw;
  210. }
  211. }
  212. template <typename SyncPrim>
  213. inline
  214. void
  215. SyncGuard<SyncPrim>::detach ()
  216. {
  217. sp = 0;
  218. }
  219. //
  220. //
  221. //
  222. template <typename SyncPrim, void (SyncPrim:: * lock_func) () const,
  223. void (SyncPrim:: * unlock_func) () const>
  224. inline
  225. SyncGuardFunc<SyncPrim, lock_func, unlock_func>::SyncGuardFunc (SyncPrim const & m)
  226. : sp (&m)
  227. {
  228. (sp->*lock_func) ();
  229. }
  230. template <typename SyncPrim, void (SyncPrim:: * lock_func) () const,
  231. void (SyncPrim:: * unlock_func) () const>
  232. inline
  233. SyncGuardFunc<SyncPrim, lock_func, unlock_func>::~SyncGuardFunc ()
  234. {
  235. if (sp)
  236. (sp->*unlock_func) ();
  237. }
  238. template <typename SyncPrim, void (SyncPrim:: * lock_func) () const,
  239. void (SyncPrim:: * unlock_func) () const>
  240. inline
  241. void
  242. SyncGuardFunc<SyncPrim, lock_func, unlock_func>::lock ()
  243. {
  244. (sp->*lock_func) ();
  245. }
  246. template <typename SyncPrim, void (SyncPrim:: * lock_func) () const,
  247. void (SyncPrim:: * unlock_func) () const>
  248. inline
  249. void
  250. SyncGuardFunc<SyncPrim, lock_func, unlock_func>::unlock ()
  251. {
  252. (sp->*unlock_func) ();
  253. }
  254. template <typename SyncPrim, void (SyncPrim:: * lock_func) () const,
  255. void (SyncPrim:: * unlock_func) () const>
  256. inline
  257. void
  258. SyncGuardFunc<SyncPrim, lock_func, unlock_func>::attach (SyncPrim const & m)
  259. {
  260. sp = &m;
  261. }
  262. template <typename SyncPrim, void (SyncPrim:: * lock_func) () const,
  263. void (SyncPrim:: * unlock_func) () const>
  264. inline
  265. void
  266. SyncGuardFunc<SyncPrim, lock_func, unlock_func>::detach ()
  267. {
  268. sp = 0;
  269. }
  270. } } // namespace log4cplus { namespace thread {
  271. #endif // LOG4CPLUS_THREAD_SYNCPRIMS_H