Warning, file /include/boost/log/detail/adaptive_mutex.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef BOOST_LOG_DETAIL_ADAPTIVE_MUTEX_HPP_INCLUDED_
0017 #define BOOST_LOG_DETAIL_ADAPTIVE_MUTEX_HPP_INCLUDED_
0018
0019 #include <boost/log/detail/config.hpp>
0020
0021 #ifdef BOOST_HAS_PRAGMA_ONCE
0022 #pragma once
0023 #endif
0024
0025 #ifndef BOOST_LOG_NO_THREADS
0026
0027 #if defined(BOOST_THREAD_POSIX)
0028 #define BOOST_LOG_ADAPTIVE_MUTEX_USE_PTHREAD
0029 #elif defined(BOOST_WINDOWS)
0030 #define BOOST_LOG_ADAPTIVE_MUTEX_USE_WINAPI
0031 #elif defined(BOOST_HAS_PTHREADS)
0032 #define BOOST_LOG_ADAPTIVE_MUTEX_USE_PTHREAD
0033 #endif
0034
0035 #if defined(BOOST_LOG_ADAPTIVE_MUTEX_USE_WINAPI)
0036
0037 #include <boost/log/detail/pause.hpp>
0038 #include <boost/winapi/thread.hpp>
0039 #include <boost/detail/interlocked.hpp>
0040
0041 #if defined(__INTEL_COMPILER) || defined(_MSC_VER)
0042 # if defined(__INTEL_COMPILER)
0043 # define BOOST_LOG_COMPILER_BARRIER __memory_barrier()
0044 # elif defined(__clang__)
0045 # define BOOST_LOG_COMPILER_BARRIER __atomic_signal_fence(__ATOMIC_SEQ_CST)
0046 # else
0047 extern "C" void _ReadWriteBarrier(void);
0048 # if defined(BOOST_MSVC)
0049 # pragma intrinsic(_ReadWriteBarrier)
0050 # endif
0051 # define BOOST_LOG_COMPILER_BARRIER _ReadWriteBarrier()
0052 # endif
0053 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
0054 # define BOOST_LOG_COMPILER_BARRIER __asm__ __volatile__("" : : : "memory")
0055 #endif
0056
0057 #include <boost/log/detail/header.hpp>
0058
0059 namespace boost {
0060
0061 BOOST_LOG_OPEN_NAMESPACE
0062
0063 namespace aux {
0064
0065
0066 class adaptive_mutex
0067 {
0068 private:
0069 enum state
0070 {
0071 initial_pause = 2,
0072 max_pause = 16
0073 };
0074
0075 long m_State;
0076
0077 public:
0078 adaptive_mutex() : m_State(0) {}
0079
0080 bool try_lock()
0081 {
0082 return (BOOST_INTERLOCKED_COMPARE_EXCHANGE(&m_State, 1L, 0L) == 0L);
0083 }
0084
0085 void lock()
0086 {
0087 #if defined(BOOST_LOG_AUX_PAUSE)
0088 unsigned int pause_count = initial_pause;
0089 #endif
0090 while (!try_lock())
0091 {
0092 #if defined(BOOST_LOG_AUX_PAUSE)
0093 if (pause_count < max_pause)
0094 {
0095 for (unsigned int i = 0; i < pause_count; ++i)
0096 {
0097 BOOST_LOG_AUX_PAUSE;
0098 }
0099 pause_count += pause_count;
0100 }
0101 else
0102 {
0103
0104 pause_count = initial_pause;
0105 boost::winapi::SwitchToThread();
0106 }
0107 #else
0108 boost::winapi::SwitchToThread();
0109 #endif
0110 }
0111 }
0112
0113 void unlock()
0114 {
0115 #if (defined(_M_IX86) || defined(_M_AMD64)) && defined(BOOST_LOG_COMPILER_BARRIER)
0116 BOOST_LOG_COMPILER_BARRIER;
0117 m_State = 0L;
0118 BOOST_LOG_COMPILER_BARRIER;
0119 #else
0120 BOOST_INTERLOCKED_EXCHANGE(&m_State, 0L);
0121 #endif
0122 }
0123
0124
0125 BOOST_DELETED_FUNCTION(adaptive_mutex(adaptive_mutex const&))
0126 BOOST_DELETED_FUNCTION(adaptive_mutex& operator= (adaptive_mutex const&))
0127 };
0128
0129 #undef BOOST_LOG_AUX_PAUSE
0130 #undef BOOST_LOG_COMPILER_BARRIER
0131
0132 }
0133
0134 BOOST_LOG_CLOSE_NAMESPACE
0135
0136 }
0137
0138 #include <boost/log/detail/footer.hpp>
0139
0140 #elif defined(BOOST_LOG_ADAPTIVE_MUTEX_USE_PTHREAD)
0141
0142 #include <pthread.h>
0143 #include <cerrno>
0144 #include <system_error>
0145 #include <boost/assert.hpp>
0146 #include <boost/assert/source_location.hpp>
0147 #include <boost/log/detail/header.hpp>
0148
0149 #if defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP)
0150 #define BOOST_LOG_ADAPTIVE_MUTEX_USE_PTHREAD_MUTEX_ADAPTIVE_NP
0151 #endif
0152
0153 namespace boost {
0154
0155 BOOST_LOG_OPEN_NAMESPACE
0156
0157 namespace aux {
0158
0159
0160 class adaptive_mutex
0161 {
0162 private:
0163 pthread_mutex_t m_State;
0164
0165 public:
0166 adaptive_mutex()
0167 {
0168 #if defined(BOOST_LOG_ADAPTIVE_MUTEX_USE_PTHREAD_MUTEX_ADAPTIVE_NP)
0169 pthread_mutexattr_t attrs;
0170 pthread_mutexattr_init(&attrs);
0171 pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_ADAPTIVE_NP);
0172
0173 const int err = pthread_mutex_init(&m_State, &attrs);
0174 pthread_mutexattr_destroy(&attrs);
0175 #else
0176 const int err = pthread_mutex_init(&m_State, NULL);
0177 #endif
0178 if (BOOST_UNLIKELY(err != 0))
0179 throw_system_error(err, "Failed to initialize an adaptive mutex", "adaptive_mutex::adaptive_mutex()", __FILE__, __LINE__);
0180 }
0181
0182 ~adaptive_mutex()
0183 {
0184 BOOST_VERIFY(pthread_mutex_destroy(&m_State) == 0);
0185 }
0186
0187 bool try_lock()
0188 {
0189 const int err = pthread_mutex_trylock(&m_State);
0190 if (err == 0)
0191 return true;
0192 if (BOOST_UNLIKELY(err != EBUSY))
0193 throw_system_error(err, "Failed to lock an adaptive mutex", "adaptive_mutex::try_lock()", __FILE__, __LINE__);
0194 return false;
0195 }
0196
0197 void lock()
0198 {
0199 const int err = pthread_mutex_lock(&m_State);
0200 if (BOOST_UNLIKELY(err != 0))
0201 throw_system_error(err, "Failed to lock an adaptive mutex", "adaptive_mutex::lock()", __FILE__, __LINE__);
0202 }
0203
0204 void unlock()
0205 {
0206 BOOST_VERIFY(pthread_mutex_unlock(&m_State) == 0);
0207 }
0208
0209
0210 BOOST_DELETED_FUNCTION(adaptive_mutex(adaptive_mutex const&))
0211 BOOST_DELETED_FUNCTION(adaptive_mutex& operator= (adaptive_mutex const&))
0212
0213 private:
0214 static BOOST_NOINLINE BOOST_LOG_NORETURN void throw_system_error(int err, const char* descr, const char* func, const char* file, int line)
0215 {
0216 boost::throw_exception(std::system_error(std::error_code(err, std::system_category()), descr), boost::source_location(file, line, func));
0217 }
0218 };
0219
0220 }
0221
0222 BOOST_LOG_CLOSE_NAMESPACE
0223
0224 }
0225
0226 #include <boost/log/detail/footer.hpp>
0227
0228 #endif
0229
0230 #endif
0231
0232 #endif