log4cplus  1.1.0
syncprims-impl.h
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //  Copyright (C) 2009-2010, 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_IMPL_H
00026 #define LOG4CPLUS_THREAD_SYNCPRIMS_IMPL_H
00027 
00028 #include <log4cplus/config.hxx>
00029 
00030 #if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
00031 #pragma once
00032 #endif
00033 
00034 #if ! defined (INSIDE_LOG4CPLUS)
00035 #  error "This header must not be be used outside log4cplus' implementation files."
00036 #endif
00037 
00038 #include <stdexcept>
00039 #include <log4cplus/thread/syncprims.h>
00040 #if defined (_WIN32)
00041 #  include <log4cplus/config/windowsh-inc.h>
00042 
00043 #elif defined (LOG4CPLUS_USE_PTHREADS)
00044 #  include <errno.h>
00045 #  include <pthread.h>
00046 #  include <semaphore.h>
00047 #  if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE)
00048 #    include <sstream>
00049 #    include <string>
00050 #    if defined (LOG4CPLUS_HAVE_SYS_TYPES_H)
00051 #      include <sys/types.h>
00052 #    endif
00053 #    if defined (LOG4CPLUS_HAVE_UNISTD_H)
00054 #      include <unistd.h>
00055 #    endif
00056 #  endif
00057 #  if defined (LOG4CPLUS_HAVE_FCNTL_H)
00058 #    include <fcntl.h>
00059 #  endif
00060 #  include <log4cplus/helpers/timehelper.h>
00061 
00062 #endif
00063 
00064 
00065 namespace log4cplus { namespace thread { namespace impl {
00066 
00067 
00068 LOG4CPLUS_EXPORT void LOG4CPLUS_ATTRIBUTE_NORETURN
00069     syncprims_throw_exception (char const * const msg,
00070     char const * const file, int line);
00071 
00072 
00073 #define LOG4CPLUS_THROW_RTE(msg) \
00074     do { syncprims_throw_exception (msg, __FILE__, __LINE__); } while (0)
00075 
00076 
00077 class ManualResetEvent;
00078 
00079 
00080 class Mutex
00081     : public MutexImplBase
00082 {
00083 public:
00084     explicit Mutex (log4cplus::thread::Mutex::Type);
00085     ~Mutex ();
00086 
00087     void lock () const;
00088     void unlock () const;
00089 
00090 private:
00091 #if defined (LOG4CPLUS_USE_PTHREADS)
00092     mutable pthread_mutex_t mtx;
00093     friend class ManualResetEvent;
00094 #elif defined (LOG4CPLUS_USE_WIN32_THREADS)
00095     mutable CRITICAL_SECTION cs;
00096 #endif
00097     
00098     Mutex (Mutex const &);
00099     Mutex & operator = (Mutex &);
00100 };
00101 
00102 
00103 typedef SyncGuard<Mutex> MutexGuard;
00104 
00105 
00106 class Semaphore
00107     : public SemaphoreImplBase
00108 {
00109 public:
00110     Semaphore (unsigned max, unsigned initial);
00111     ~Semaphore ();
00112 
00113     void lock () const;
00114     void unlock () const;
00115 
00116 private:
00117 #if defined (LOG4CPLUS_USE_PTHREADS)
00118 #  if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE)
00119     sem_t * sem;
00120 #  else
00121     mutable sem_t sem;
00122 #  endif
00123 #elif defined (LOG4CPLUS_USE_WIN32_THREADS)
00124     HANDLE sem;
00125 #endif
00126 
00127     Semaphore (Semaphore const &);
00128     Semaphore & operator = (Semaphore const &);
00129 };
00130 
00131 
00132 typedef SyncGuard<Semaphore> SemaphoreGuard;
00133 
00134 
00135 class FairMutex
00136     : public FairMutexImplBase
00137 {
00138 public:
00139     FairMutex ();
00140     ~FairMutex ();
00141 
00142     void lock () const;
00143     void unlock () const;
00144 
00145 private:
00146 #if defined (LOG4CPLUS_USE_PTHREADS)
00147     Semaphore sem;
00148 #elif defined (LOG4CPLUS_USE_WIN32_THREADS)
00149     HANDLE mtx;
00150 #endif
00151 
00152     FairMutex (FairMutex const &);
00153     FairMutex & operator = (FairMutex &);
00154 };
00155 
00156 
00157 typedef SyncGuard<FairMutex> FairMutexGuard;
00158 
00159 
00160 class ManualResetEvent
00161     : public ManualResetEventImplBase
00162 {
00163 public:
00164     ManualResetEvent (bool = false);
00165     ~ManualResetEvent ();
00166 
00167     void signal () const;
00168     void wait () const;
00169     bool timed_wait (unsigned long msec) const;
00170     void reset () const;
00171 
00172 private:
00173 #if defined (LOG4CPLUS_USE_PTHREADS)
00174     mutable pthread_cond_t cv;
00175     mutable Mutex mtx;
00176     mutable volatile unsigned sigcount;
00177     mutable volatile bool signaled;
00178 #elif defined (LOG4CPLUS_USE_WIN32_THREADS)
00179     HANDLE ev;
00180 #endif
00181 
00182     ManualResetEvent (ManualResetEvent const &);
00183     ManualResetEvent & operator = (ManualResetEvent const &);
00184 };
00185 
00186 
00187 class SharedMutex
00188     : public SharedMutexImplBase
00189 {
00190 public:
00191     SharedMutex ();
00192     ~SharedMutex ();
00193 
00194     void rdlock () const;
00195     void wrlock () const;
00196     void rdunlock () const;
00197     void wrunlock () const;
00198 
00199 private:
00200 #if defined (LOG4CPLUS_POOR_MANS_SHAREDMUTEX)
00201     Mutex m1;
00202     Mutex m2;
00203     Mutex m3;
00204     Semaphore w;
00205     mutable unsigned writer_count;
00206     Semaphore r;
00207     mutable unsigned reader_count;
00208 
00209 #elif defined (LOG4CPLUS_USE_PTHREADS)
00210     void unlock () const;
00211 
00212     mutable pthread_rwlock_t rwl;
00213 
00214 #elif defined (LOG4CPLUS_USE_SRW_LOCK)
00215     mutable SRWLOCK srwl;
00216 
00217 #endif
00218 
00219     SharedMutex (SharedMutex const &);
00220     SharedMutex & operator = (SharedMutex const &);
00221 };
00222 
00223 
00224 } } } // namespace log4cplus { namespace thread { namespace impl {
00225 
00226 
00227 // Include the appropriate implementations of the classes declared
00228 // above.
00229 
00230 #if defined (LOG4CPLUS_USE_PTHREADS)
00231 #  include <log4cplus/thread/impl/syncprims-pthreads.h>
00232 #elif defined (LOG4CPLUS_USE_WIN32_THREADS)
00233 #  include <log4cplus/thread/impl/syncprims-win32.h>
00234 #endif
00235 
00236 
00237 #undef LOG4CPLUS_THROW_RTE
00238 
00239 
00240 #endif // LOG4CPLUS_THREAD_SYNCPRIMS_IMPL_H