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