log4cplus  2.0.0
syncprims.h
Go to the documentation of this file.
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