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_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