2 * Copyright Andrey Semashev 2007 - 2015.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
8 * \file light_rw_mutex.cpp
9 * \author Andrey Semashev
12 * \brief This header is the Boost.Log library implementation, see the library documentation
13 * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
16 #include <boost/log/detail/config.hpp>
17 #include <boost/log/detail/light_rw_mutex.hpp>
19 #if !defined(BOOST_LOG_NO_THREADS)
21 #if !defined(BOOST_LOG_LWRWMUTEX_USE_PTHREAD) && !defined(BOOST_LOG_LWRWMUTEX_USE_SRWLOCK)
25 #include <boost/assert.hpp>
26 #include <boost/align/aligned_alloc.hpp>
27 #include <boost/thread/shared_mutex.hpp>
28 #include <boost/log/utility/once_block.hpp>
30 #include <boost/winapi/basic_types.hpp>
31 #include <boost/winapi/dll.hpp>
33 #include <boost/log/detail/header.hpp>
37 BOOST_LOG_OPEN_NAMESPACE
41 BOOST_LOG_ANONYMOUS_NAMESPACE
{
43 struct BOOST_LOG_MAY_ALIAS mutex_impl
{ void* p
; }; // has the same layout as SRWLOCK and light_rw_mutex::m_Mutex
45 typedef void (BOOST_WINAPI_WINAPI_CC
*init_fun_t
)(mutex_impl
*);
46 typedef void (BOOST_WINAPI_WINAPI_CC
*destroy_fun_t
)(mutex_impl
*);
47 typedef void (BOOST_WINAPI_WINAPI_CC
*lock_exclusive_fun_t
)(mutex_impl
*);
48 typedef void (BOOST_WINAPI_WINAPI_CC
*lock_shared_fun_t
)(mutex_impl
*);
49 typedef void (BOOST_WINAPI_WINAPI_CC
*unlock_exclusive_fun_t
)(mutex_impl
*);
50 typedef void (BOOST_WINAPI_WINAPI_CC
*unlock_shared_fun_t
)(mutex_impl
*);
52 //! A complement stub function for InitializeSRWLock
53 void BOOST_WINAPI_WINAPI_CC
DeinitializeSRWLock(mutex_impl
*)
57 // The Boost.Thread-based implementation
58 void BOOST_WINAPI_WINAPI_CC
InitializeSharedMutex(mutex_impl
* mtx
)
60 // To avoid cache line aliasing we do aligned memory allocation here
63 // Allocation size is the minimum number of cache lines to accommodate shared_mutex
66 (sizeof(shared_mutex
) + BOOST_LOG_CPU_CACHE_LINE_SIZE
- 1u) / BOOST_LOG_CPU_CACHE_LINE_SIZE
68 * BOOST_LOG_CPU_CACHE_LINE_SIZE
70 mtx
->p
= alignment::aligned_alloc(BOOST_LOG_CPU_CACHE_LINE_SIZE
, size
);
71 BOOST_ASSERT(mtx
->p
!= NULL
);
72 new (mtx
->p
) shared_mutex();
75 void BOOST_WINAPI_WINAPI_CC
DeinitializeSharedMutex(mutex_impl
* mtx
)
77 static_cast< shared_mutex
* >(mtx
->p
)->~shared_mutex();
78 alignment::aligned_free(mtx
->p
);
82 void BOOST_WINAPI_WINAPI_CC
ExclusiveLockSharedMutex(mutex_impl
* mtx
)
84 static_cast< shared_mutex
* >(mtx
->p
)->lock();
87 void BOOST_WINAPI_WINAPI_CC
SharedLockSharedMutex(mutex_impl
* mtx
)
89 static_cast< shared_mutex
* >(mtx
->p
)->lock_shared();
92 void BOOST_WINAPI_WINAPI_CC
ExclusiveUnlockSharedMutex(mutex_impl
* mtx
)
94 static_cast< shared_mutex
* >(mtx
->p
)->unlock();
97 void BOOST_WINAPI_WINAPI_CC
SharedUnlockSharedMutex(mutex_impl
* mtx
)
99 static_cast< shared_mutex
* >(mtx
->p
)->unlock_shared();
102 // Pointers to the actual implementation functions
103 init_fun_t g_pInitializeLWRWMutex
= NULL
;
104 destroy_fun_t g_pDestroyLWRWMutex
= NULL
;
105 lock_exclusive_fun_t g_pLockExclusiveLWRWMutex
= NULL
;
106 lock_shared_fun_t g_pLockSharedLWRWMutex
= NULL
;
107 unlock_exclusive_fun_t g_pUnlockExclusiveLWRWMutex
= NULL
;
108 unlock_shared_fun_t g_pUnlockSharedLWRWMutex
= NULL
;
110 //! The function dynamically initializes the implementation pointers
111 void init_light_rw_mutex_impl()
113 boost::winapi::HMODULE_ hKernel32
= boost::winapi::GetModuleHandleW(L
"kernel32.dll");
116 g_pInitializeLWRWMutex
=
117 (init_fun_t
)boost::winapi::get_proc_address(hKernel32
, "InitializeSRWLock");
118 if (g_pInitializeLWRWMutex
)
120 g_pLockExclusiveLWRWMutex
=
121 (lock_exclusive_fun_t
)boost::winapi::get_proc_address(hKernel32
, "AcquireSRWLockExclusive");
122 if (g_pLockExclusiveLWRWMutex
)
124 g_pUnlockExclusiveLWRWMutex
=
125 (unlock_exclusive_fun_t
)boost::winapi::get_proc_address(hKernel32
, "ReleaseSRWLockExclusive");
126 if (g_pUnlockExclusiveLWRWMutex
)
128 g_pLockSharedLWRWMutex
=
129 (lock_shared_fun_t
)boost::winapi::get_proc_address(hKernel32
, "AcquireSRWLockShared");
130 if (g_pLockSharedLWRWMutex
)
132 g_pUnlockSharedLWRWMutex
=
133 (unlock_shared_fun_t
)boost::winapi::get_proc_address(hKernel32
, "ReleaseSRWLockShared");
134 if (g_pUnlockSharedLWRWMutex
)
136 g_pDestroyLWRWMutex
= &DeinitializeSRWLock
;
145 // Current OS doesn't have support for SRWLOCK, use Boost.Thread instead
146 g_pInitializeLWRWMutex
= &InitializeSharedMutex
;
147 g_pDestroyLWRWMutex
= &DeinitializeSharedMutex
;
148 g_pLockExclusiveLWRWMutex
= &ExclusiveLockSharedMutex
;
149 g_pUnlockExclusiveLWRWMutex
= &ExclusiveUnlockSharedMutex
;
150 g_pLockSharedLWRWMutex
= &SharedLockSharedMutex
;
151 g_pUnlockSharedLWRWMutex
= &SharedUnlockSharedMutex
;
156 BOOST_LOG_API
light_rw_mutex::light_rw_mutex()
158 BOOST_LOG_ONCE_BLOCK()
160 init_light_rw_mutex_impl();
162 g_pInitializeLWRWMutex((mutex_impl
*)&m_Mutex
);
165 BOOST_LOG_API
light_rw_mutex::~light_rw_mutex()
167 g_pDestroyLWRWMutex((mutex_impl
*)&m_Mutex
);
170 BOOST_LOG_API
void light_rw_mutex::lock_shared()
172 g_pLockSharedLWRWMutex((mutex_impl
*)&m_Mutex
);
175 BOOST_LOG_API
void light_rw_mutex::unlock_shared()
177 g_pUnlockSharedLWRWMutex((mutex_impl
*)&m_Mutex
);
180 BOOST_LOG_API
void light_rw_mutex::lock()
182 g_pLockExclusiveLWRWMutex((mutex_impl
*)&m_Mutex
);
185 BOOST_LOG_API
void light_rw_mutex::unlock()
187 g_pUnlockExclusiveLWRWMutex((mutex_impl
*)&m_Mutex
);
192 BOOST_LOG_CLOSE_NAMESPACE
// namespace log
196 #include <boost/log/detail/footer.hpp>
198 #endif // !defined(BOOST_LOG_LWRWMUTEX_USE_PTHREAD) && !defined(BOOST_LOG_LWRWMUTEX_USE_SRWLOCK)
200 #endif // !defined(BOOST_LOG_NO_THREADS)