log4cplus
2.0.0
|
00001 // -*- C++ -*- 00002 // Copyright (C) 2010-2015, Vaclav Haisman. All rights reserved. 00003 // 00004 // Redistribution and use in source and binary forms, with or without modifica- 00005 // tion, are permitted provided that the following conditions are met: 00006 // 00007 // 1. Redistributions of source code must retain the above copyright notice, 00008 // this list of conditions and the following disclaimer. 00009 // 00010 // 2. Redistributions in binary form must reproduce the above copyright notice, 00011 // this list of conditions and the following disclaimer in the documentation 00012 // and/or other materials provided with the distribution. 00013 // 00014 // THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, 00015 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 00016 // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00017 // APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 00018 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- 00019 // DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00020 // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 00021 // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00022 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00023 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00024 00025 #ifndef LOG4CPLUS_THREAD_SYNCPRIMS_H 00026 #define LOG4CPLUS_THREAD_SYNCPRIMS_H 00027 00028 #include <log4cplus/config.hxx> 00029 00030 #if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) 00031 #pragma once 00032 #endif 00033 00034 #include <mutex> 00035 #include <condition_variable> 00036 00037 00038 namespace log4cplus { namespace thread { 00039 00040 00041 template <typename SyncPrim> 00042 class SyncGuard 00043 { 00044 public: 00045 SyncGuard (); 00046 SyncGuard (SyncPrim const &); 00047 ~SyncGuard (); 00048 SyncGuard (SyncGuard const &) = delete; 00049 SyncGuard & operator = (SyncGuard const &) = delete; 00050 00051 00052 void lock (); 00053 void unlock (); 00054 void attach (SyncPrim const &); 00055 void attach_and_lock (SyncPrim const &); 00056 void detach (); 00057 00058 private: 00059 SyncPrim const * sp; 00060 }; 00061 00062 00063 class LOG4CPLUS_EXPORT Mutex 00064 { 00065 public: 00066 Mutex (); 00067 ~Mutex (); 00068 Mutex (Mutex const &) = delete; 00069 Mutex & operator = (Mutex const &) = delete; 00070 00071 void lock () const; 00072 void unlock () const; 00073 00074 private: 00075 LOG4CPLUS_THREADED (mutable std::recursive_mutex mtx;) 00076 }; 00077 00078 00079 typedef SyncGuard<Mutex> MutexGuard; 00080 00081 00082 class LOG4CPLUS_EXPORT Semaphore 00083 { 00084 public: 00085 Semaphore (unsigned max, unsigned initial); 00086 ~Semaphore (); 00087 Semaphore (Semaphore const &) = delete; 00088 Semaphore & operator = (Semaphore const &) = delete; 00089 00090 void lock () const; 00091 void unlock () const; 00092 00093 private: 00094 #if ! defined (LOG4CPLUS_SINGLE_THREADED) 00095 mutable std::mutex mtx; 00096 mutable std::condition_variable cv; 00097 mutable unsigned max; 00098 mutable unsigned val; 00099 #endif 00100 }; 00101 00102 00103 typedef SyncGuard<Semaphore> SemaphoreGuard; 00104 00105 00106 class LOG4CPLUS_EXPORT ManualResetEvent 00107 { 00108 public: 00109 explicit ManualResetEvent (bool = false); 00110 ~ManualResetEvent (); 00111 ManualResetEvent (ManualResetEvent const &) = delete; 00112 ManualResetEvent & operator = (ManualResetEvent const &) = delete; 00113 00114 void signal () const; 00115 void wait () const; 00116 bool timed_wait (unsigned long msec) const; 00117 void reset () const; 00118 00119 private: 00120 #if ! defined (LOG4CPLUS_SINGLE_THREADED) 00121 mutable std::mutex mtx; 00122 mutable std::condition_variable cv; 00123 mutable bool signaled; 00124 mutable unsigned sigcount; 00125 #endif 00126 }; 00127 00128 00129 class SharedMutexImplBase 00130 { 00131 protected: 00132 ~SharedMutexImplBase (); 00133 }; 00134 00135 00136 template <typename SyncPrim, void (SyncPrim:: * lock_func) () const, 00137 void (SyncPrim:: * unlock_func) () const> 00138 class SyncGuardFunc 00139 { 00140 public: 00141 SyncGuardFunc (SyncPrim const &); 00142 ~SyncGuardFunc (); 00143 00144 void lock (); 00145 void unlock (); 00146 void attach (SyncPrim const &); 00147 void detach (); 00148 00149 private: 00150 SyncPrim const * sp; 00151 00152 SyncGuardFunc (SyncGuardFunc const &); 00153 SyncGuardFunc & operator = (SyncGuardFunc const &); 00154 }; 00155 00156 00157 class LOG4CPLUS_EXPORT SharedMutex 00158 { 00159 public: 00160 SharedMutex (); 00161 ~SharedMutex (); 00162 00163 void rdlock () const; 00164 void rdunlock () const; 00165 00166 void wrlock () const; 00167 void wrunlock () const; 00168 00169 private: 00170 SharedMutexImplBase * sm; 00171 00172 SharedMutex (SharedMutex const &); 00173 SharedMutex & operator = (SharedMutex const &); 00174 }; 00175 00176 00177 typedef SyncGuardFunc<SharedMutex, &SharedMutex::rdlock, 00178 &SharedMutex::rdunlock> SharedMutexReaderGuard; 00179 00180 00181 typedef SyncGuardFunc<SharedMutex, &SharedMutex::wrlock, 00182 &SharedMutex::wrunlock> SharedMutexWriterGuard; 00183 00184 00185 // 00186 // 00187 // 00188 00189 template <typename SyncPrim> 00190 inline 00191 SyncGuard<SyncPrim>::SyncGuard () 00192 : sp (0) 00193 { } 00194 00195 00196 template <typename SyncPrim> 00197 inline 00198 SyncGuard<SyncPrim>::SyncGuard (SyncPrim const & m) 00199 : sp (&m) 00200 { 00201 sp->lock (); 00202 } 00203 00204 00205 template <typename SyncPrim> 00206 inline 00207 SyncGuard<SyncPrim>::~SyncGuard () 00208 { 00209 if (sp) 00210 sp->unlock (); 00211 } 00212 00213 00214 template <typename SyncPrim> 00215 inline 00216 void 00217 SyncGuard<SyncPrim>::lock () 00218 { 00219 sp->lock (); 00220 } 00221 00222 00223 template <typename SyncPrim> 00224 inline 00225 void 00226 SyncGuard<SyncPrim>::unlock () 00227 { 00228 sp->unlock (); 00229 } 00230 00231 00232 template <typename SyncPrim> 00233 inline 00234 void 00235 SyncGuard<SyncPrim>::attach (SyncPrim const & m) 00236 { 00237 sp = &m; 00238 } 00239 00240 00241 template <typename SyncPrim> 00242 inline 00243 void 00244 SyncGuard<SyncPrim>::attach_and_lock (SyncPrim const & m) 00245 { 00246 attach (m); 00247 try 00248 { 00249 lock(); 00250 } 00251 catch (...) 00252 { 00253 detach (); 00254 throw; 00255 } 00256 } 00257 00258 00259 template <typename SyncPrim> 00260 inline 00261 void 00262 SyncGuard<SyncPrim>::detach () 00263 { 00264 sp = 0; 00265 } 00266 00267 00268 // 00269 // 00270 // 00271 00272 template <typename SyncPrim, void (SyncPrim:: * lock_func) () const, 00273 void (SyncPrim:: * unlock_func) () const> 00274 inline 00275 SyncGuardFunc<SyncPrim, lock_func, unlock_func>::SyncGuardFunc (SyncPrim const & m) 00276 : sp (&m) 00277 { 00278 (sp->*lock_func) (); 00279 } 00280 00281 00282 template <typename SyncPrim, void (SyncPrim:: * lock_func) () const, 00283 void (SyncPrim:: * unlock_func) () const> 00284 inline 00285 SyncGuardFunc<SyncPrim, lock_func, unlock_func>::~SyncGuardFunc () 00286 { 00287 if (sp) 00288 (sp->*unlock_func) (); 00289 } 00290 00291 00292 template <typename SyncPrim, void (SyncPrim:: * lock_func) () const, 00293 void (SyncPrim:: * unlock_func) () const> 00294 inline 00295 void 00296 SyncGuardFunc<SyncPrim, lock_func, unlock_func>::lock () 00297 { 00298 (sp->*lock_func) (); 00299 } 00300 00301 00302 template <typename SyncPrim, void (SyncPrim:: * lock_func) () const, 00303 void (SyncPrim:: * unlock_func) () const> 00304 inline 00305 void 00306 SyncGuardFunc<SyncPrim, lock_func, unlock_func>::unlock () 00307 { 00308 (sp->*unlock_func) (); 00309 } 00310 00311 00312 template <typename SyncPrim, void (SyncPrim:: * lock_func) () const, 00313 void (SyncPrim:: * unlock_func) () const> 00314 inline 00315 void 00316 SyncGuardFunc<SyncPrim, lock_func, unlock_func>::attach (SyncPrim const & m) 00317 { 00318 sp = &m; 00319 } 00320 00321 00322 template <typename SyncPrim, void (SyncPrim:: * lock_func) () const, 00323 void (SyncPrim:: * unlock_func) () const> 00324 inline 00325 void 00326 SyncGuardFunc<SyncPrim, lock_func, unlock_func>::detach () 00327 { 00328 sp = 0; 00329 } 00330 00331 00332 } } // namespace log4cplus { namespace thread { 00333 00334 00335 #endif // LOG4CPLUS_THREAD_SYNCPRIMS_H