syncprims-impl.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. // -*- C++ -*-
  2. // Copyright (C) 2009-2015, 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_IMPL_H
  25. #define LOG4CPLUS_THREAD_SYNCPRIMS_IMPL_H
  26. #include <log4cplus/config.hxx>
  27. #if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
  28. #pragma once
  29. #endif
  30. #if ! defined (INSIDE_LOG4CPLUS)
  31. # error "This header must not be be used outside log4cplus' implementation files."
  32. #endif
  33. #include <stdexcept>
  34. #include <log4cplus/thread/syncprims.h>
  35. #if defined (LOG4CPLUS_WITH_CXX11_THREADS)
  36. # include <mutex>
  37. # include <thread>
  38. # include <condition_variable>
  39. #elif defined (_WIN32)
  40. # include <log4cplus/config/windowsh-inc.h>
  41. #elif defined (LOG4CPLUS_USE_PTHREADS)
  42. # include <errno.h>
  43. # include <pthread.h>
  44. # include <semaphore.h>
  45. # if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE)
  46. # include <sstream>
  47. # include <string>
  48. # if defined (LOG4CPLUS_HAVE_SYS_TYPES_H)
  49. # include <sys/types.h>
  50. # endif
  51. # if defined (LOG4CPLUS_HAVE_UNISTD_H)
  52. # include <unistd.h>
  53. # endif
  54. # endif
  55. # if defined (LOG4CPLUS_HAVE_FCNTL_H)
  56. # include <fcntl.h>
  57. # endif
  58. # include <log4cplus/helpers/timehelper.h>
  59. #endif
  60. namespace log4cplus { namespace thread { namespace impl {
  61. LOG4CPLUS_EXPORT void LOG4CPLUS_ATTRIBUTE_NORETURN
  62. syncprims_throw_exception (char const * const msg,
  63. char const * const file, int line);
  64. #define LOG4CPLUS_THROW_RTE(msg) \
  65. do { syncprims_throw_exception (msg, __FILE__, __LINE__); } while (0)
  66. class ManualResetEvent;
  67. class Mutex
  68. : public MutexImplBase
  69. {
  70. public:
  71. explicit Mutex (log4cplus::thread::Mutex::Type);
  72. ~Mutex ();
  73. void lock () const;
  74. void unlock () const;
  75. private:
  76. #if defined (LOG4CPLUS_WITH_CXX11_THREADS)
  77. mutable std::recursive_mutex mtx;
  78. #elif defined (LOG4CPLUS_USE_PTHREADS)
  79. mutable pthread_mutex_t mtx;
  80. friend class ManualResetEvent;
  81. #elif defined (LOG4CPLUS_USE_WIN32_THREADS)
  82. mutable CRITICAL_SECTION cs;
  83. #endif
  84. Mutex (Mutex const &);
  85. Mutex & operator = (Mutex &);
  86. };
  87. typedef SyncGuard<Mutex> MutexGuard;
  88. class Semaphore
  89. : public SemaphoreImplBase
  90. {
  91. public:
  92. Semaphore (unsigned max, unsigned initial);
  93. ~Semaphore ();
  94. void lock () const;
  95. void unlock () const;
  96. private:
  97. #if defined (LOG4CPLUS_WITH_CXX11_THREADS)
  98. mutable std::mutex mtx;
  99. mutable std::condition_variable cv;
  100. mutable unsigned max;
  101. mutable unsigned val;
  102. #elif defined (LOG4CPLUS_USE_PTHREADS)
  103. # if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE)
  104. sem_t * sem;
  105. # else
  106. mutable sem_t sem;
  107. # endif
  108. #elif defined (LOG4CPLUS_USE_WIN32_THREADS)
  109. HANDLE sem;
  110. #endif
  111. Semaphore (Semaphore const &);
  112. Semaphore & operator = (Semaphore const &);
  113. };
  114. typedef SyncGuard<Semaphore> SemaphoreGuard;
  115. class FairMutex
  116. : public FairMutexImplBase
  117. {
  118. public:
  119. FairMutex ();
  120. ~FairMutex ();
  121. void lock () const;
  122. void unlock () const;
  123. private:
  124. #if defined (LOG4CPLUS_USE_PTHREADS) \
  125. || defined (LOG4CPLUS_WITH_CXX11_THREADS)
  126. Semaphore sem;
  127. #elif defined (LOG4CPLUS_USE_WIN32_THREADS)
  128. HANDLE mtx;
  129. #endif
  130. FairMutex (FairMutex const &);
  131. FairMutex & operator = (FairMutex &);
  132. };
  133. typedef SyncGuard<FairMutex> FairMutexGuard;
  134. class ManualResetEvent
  135. : public ManualResetEventImplBase
  136. {
  137. public:
  138. ManualResetEvent (bool = false);
  139. ~ManualResetEvent ();
  140. void signal () const;
  141. void wait () const;
  142. bool timed_wait (unsigned long msec) const;
  143. void reset () const;
  144. private:
  145. #if defined (LOG4CPLUS_WITH_CXX11_THREADS)
  146. mutable std::mutex mtx;
  147. mutable std::condition_variable cv;
  148. mutable unsigned sigcount;
  149. mutable bool signaled;
  150. #elif defined (LOG4CPLUS_USE_PTHREADS)
  151. mutable pthread_cond_t cv;
  152. mutable Mutex mtx;
  153. mutable volatile unsigned sigcount;
  154. mutable volatile bool signaled;
  155. #elif defined (LOG4CPLUS_USE_WIN32_THREADS)
  156. HANDLE ev;
  157. #endif
  158. ManualResetEvent (ManualResetEvent const &);
  159. ManualResetEvent & operator = (ManualResetEvent const &);
  160. };
  161. class SharedMutex
  162. : public SharedMutexImplBase
  163. {
  164. public:
  165. SharedMutex ();
  166. ~SharedMutex ();
  167. void rdlock () const;
  168. void wrlock () const;
  169. void rdunlock () const;
  170. void wrunlock () const;
  171. private:
  172. #if defined (LOG4CPLUS_POOR_MANS_SHAREDMUTEX) \
  173. || defined (LOG4CPLUS_WITH_CXX11_THREADS)
  174. Mutex m1;
  175. Mutex m2;
  176. Mutex m3;
  177. Semaphore w;
  178. mutable unsigned writer_count;
  179. Semaphore r;
  180. mutable unsigned reader_count;
  181. #elif defined (LOG4CPLUS_USE_PTHREADS)
  182. void unlock () const;
  183. mutable pthread_rwlock_t rwl;
  184. #elif defined (LOG4CPLUS_USE_SRW_LOCK)
  185. mutable SRWLOCK srwl;
  186. #endif
  187. SharedMutex (SharedMutex const &);
  188. SharedMutex & operator = (SharedMutex const &);
  189. };
  190. } } } // namespace log4cplus { namespace thread { namespace impl {
  191. // Include the appropriate implementations of the classes declared
  192. // above.
  193. #if defined (LOG4CPLUS_WITH_CXX11_THREADS)
  194. # include <log4cplus/thread/impl/syncprims-cxx11.h>
  195. #elif defined (LOG4CPLUS_USE_PTHREADS)
  196. # include <log4cplus/thread/impl/syncprims-pthreads.h>
  197. #elif defined (LOG4CPLUS_USE_WIN32_THREADS)
  198. # include <log4cplus/thread/impl/syncprims-win32.h>
  199. #endif
  200. #undef LOG4CPLUS_THROW_RTE
  201. #endif // LOG4CPLUS_THREAD_SYNCPRIMS_IMPL_H