log4cplus  2.0.0
syncprims-pub-impl.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_PUB_IMPL_H
00026 #define LOG4CPLUS_THREAD_SYNCPRIMS_PUB_IMPL_H
00027 
00028 #include <log4cplus/config.hxx>
00029 
00030 #if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
00031 #pragma once
00032 #endif
00033 
00034 #include <algorithm>
00035 
00036 #if (defined (LOG4CPLUS_INLINES_ARE_EXPORTED)           \
00037     && defined (LOG4CPLUS_BUILD_DLL))                   \
00038     || defined (LOG4CPLUS_ENABLE_SYNCPRIMS_PUB_IMPL)
00039 #include <log4cplus/thread/syncprims.h>
00040 
00041 #if ! defined (LOG4CPLUS_SINGLE_THREADED)
00042 #  include <log4cplus/thread/impl/syncprims-impl.h>
00043 #endif
00044 
00045 #define LOG4CPLUS_THROW_RTE(msg) \
00046     do { log4cplus::thread::impl::syncprims_throw_exception (msg, __FILE__, \
00047             __LINE__); } while (0)
00048 
00049 namespace log4cplus { namespace thread {
00050 
00051 namespace impl
00052 {
00053 
00054 LOG4CPLUS_EXPORT void LOG4CPLUS_ATTRIBUTE_NORETURN
00055     syncprims_throw_exception(char const * const msg,
00056     char const * const file, int line);
00057 
00058 }
00059 
00060 //
00061 //
00062 //
00063 
00064 LOG4CPLUS_INLINE_EXPORT
00065 Mutex::Mutex ()
00066     LOG4CPLUS_THREADED (: mtx ())
00067 { }
00068 
00069 
00070 LOG4CPLUS_INLINE_EXPORT
00071 Mutex::~Mutex ()
00072 { }
00073 
00074 
00075 LOG4CPLUS_INLINE_EXPORT
00076 void
00077 Mutex::lock () const
00078 {
00079     LOG4CPLUS_THREADED (mtx.lock ());
00080 }
00081 
00082 
00083 LOG4CPLUS_INLINE_EXPORT
00084 void
00085 Mutex::unlock () const
00086 {
00087     LOG4CPLUS_THREADED (mtx.unlock ());
00088 }
00089 
00090 
00091 //
00092 //
00093 //
00094 
00095 LOG4CPLUS_INLINE_EXPORT
00096 Semaphore::Semaphore (unsigned LOG4CPLUS_THREADED (max_),
00097     unsigned LOG4CPLUS_THREADED (initial))
00098 #if ! defined (LOG4CPLUS_SINGLE_THREADED)
00099     : max (max_)
00100     , val ((std::min) (max, initial))
00101 #endif
00102 { }
00103 
00104 
00105 LOG4CPLUS_INLINE_EXPORT
00106 Semaphore::~Semaphore ()
00107 { }
00108 
00109 
00110 LOG4CPLUS_INLINE_EXPORT
00111 void
00112 Semaphore::lock () const
00113 {
00114 #if ! defined (LOG4CPLUS_SINGLE_THREADED)
00115     std::lock_guard<std::mutex> guard (mtx);
00116 
00117     if (val >= max)
00118         LOG4CPLUS_THROW_RTE ("Semaphore::unlock(): val >= max");
00119 
00120     ++val;
00121     cv.notify_all ();
00122 #endif
00123 }
00124 
00125 
00126 LOG4CPLUS_INLINE_EXPORT
00127 void
00128 Semaphore::unlock () const
00129 {
00130 #if ! defined (LOG4CPLUS_SINGLE_THREADED)
00131     std::unique_lock<std::mutex> guard (mtx);
00132 
00133     while (val == 0)
00134         cv.wait (guard);
00135 
00136     --val;
00137 
00138     if (LOG4CPLUS_UNLIKELY(val >= max))
00139         LOG4CPLUS_THROW_RTE ("Semaphore::unlock(): val >= max");
00140 #endif
00141 }
00142 
00143 
00144 //
00145 //
00146 //
00147 
00148 LOG4CPLUS_INLINE_EXPORT
00149 ManualResetEvent::ManualResetEvent (bool LOG4CPLUS_THREADED (sig))
00150 #if ! defined (LOG4CPLUS_SINGLE_THREADED)
00151     : signaled (sig)
00152     , sigcount (0)
00153 #endif
00154 { }
00155 
00156 
00157 LOG4CPLUS_INLINE_EXPORT
00158 ManualResetEvent::~ManualResetEvent ()
00159 { }
00160 
00161 
00162 LOG4CPLUS_INLINE_EXPORT
00163 void
00164 ManualResetEvent::signal () const
00165 {
00166 #if ! defined (LOG4CPLUS_SINGLE_THREADED)
00167     std::unique_lock<std::mutex> guard (mtx);
00168 
00169     signaled = true;
00170     sigcount += 1;
00171     cv.notify_all ();
00172 #endif
00173 }
00174 
00175 
00176 LOG4CPLUS_INLINE_EXPORT
00177 void
00178 ManualResetEvent::wait () const
00179 {
00180 #if ! defined (LOG4CPLUS_SINGLE_THREADED)
00181     std::unique_lock<std::mutex> guard (mtx);
00182 
00183     if (! signaled)
00184     {
00185         unsigned prev_count = sigcount;
00186         do
00187         {
00188             cv.wait (guard);
00189         }
00190         while (prev_count == sigcount);
00191     }
00192 #endif
00193 }
00194 
00195 
00196 LOG4CPLUS_INLINE_EXPORT
00197 bool
00198 ManualResetEvent::timed_wait (unsigned long LOG4CPLUS_THREADED (msec)) const
00199 {
00200 #if defined (LOG4CPLUS_SINGLE_THREADED)
00201     return true;
00202 
00203 #else
00204     std::unique_lock<std::mutex> guard (mtx);
00205 
00206     if (! signaled)
00207     {
00208         unsigned prev_count = sigcount;
00209 
00210         std::chrono::steady_clock::time_point const wait_until_time
00211             = std::chrono::steady_clock::now ()
00212             + std::chrono::milliseconds (msec);
00213 
00214         do
00215         {
00216             int ret = static_cast<int>(
00217                 cv.wait_until (guard, wait_until_time));
00218             switch (ret)
00219             {
00220             case static_cast<int>(std::cv_status::no_timeout):
00221                 break;
00222 
00223             case static_cast<int>(std::cv_status::timeout):
00224                 return false;
00225 
00226             default:
00227                 guard.unlock ();
00228                 guard.release ();
00229                 LOG4CPLUS_THROW_RTE ("ManualResetEvent::timed_wait");
00230             }
00231         }
00232         while (prev_count == sigcount);
00233     }
00234 
00235     return true;
00236 #endif
00237 }
00238 
00239 
00240 LOG4CPLUS_INLINE_EXPORT
00241 void
00242 ManualResetEvent::reset () const
00243 {
00244 #if ! defined (LOG4CPLUS_SINGLE_THREADED)
00245     std::lock_guard<std::mutex> guard (mtx);
00246 
00247     signaled = false;
00248 #endif
00249 }
00250 
00251 
00252 //
00253 //
00254 //
00255 
00256 LOG4CPLUS_INLINE_EXPORT
00257 SharedMutexImplBase::~SharedMutexImplBase ()
00258 { }
00259 
00260 
00261 //
00262 //
00263 //
00264 
00265 LOG4CPLUS_INLINE_EXPORT
00266 SharedMutex::SharedMutex ()
00267     : sm (LOG4CPLUS_THREADED (new impl::SharedMutex))
00268 { }
00269 
00270 
00271 LOG4CPLUS_INLINE_EXPORT
00272 SharedMutex::~SharedMutex ()
00273 {
00274     LOG4CPLUS_THREADED (delete static_cast<impl::SharedMutex *>(sm));
00275 }
00276 
00277 
00278 LOG4CPLUS_INLINE_EXPORT
00279 void
00280 SharedMutex::rdlock () const
00281 {
00282     LOG4CPLUS_THREADED (static_cast<impl::SharedMutex *>(sm)->rdlock ());
00283 }
00284 
00285 
00286 LOG4CPLUS_INLINE_EXPORT
00287 void
00288 SharedMutex::wrlock () const
00289 {
00290     LOG4CPLUS_THREADED (static_cast<impl::SharedMutex *>(sm)->wrlock ());
00291 }
00292 
00293 
00294 LOG4CPLUS_INLINE_EXPORT
00295 void
00296 SharedMutex::rdunlock () const
00297 {
00298     LOG4CPLUS_THREADED (static_cast<impl::SharedMutex *>(sm)->rdunlock ());
00299 }
00300 
00301 
00302 LOG4CPLUS_INLINE_EXPORT
00303 void
00304 SharedMutex::wrunlock () const
00305 {
00306     LOG4CPLUS_THREADED (static_cast<impl::SharedMutex *>(sm)->wrunlock ());
00307 }
00308 
00309 
00310 } } // namespace log4cplus { namespace thread {
00311 
00312 #endif // LOG4CPLUS_ENABLE_SYNCPRIMS_PUB_IMPL
00313 
00314 #endif // LOG4CPLUS_THREAD_SYNCPRIMS_PUB_IMPL_H