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 (WINAPI
*init_fun_t
)(mutex_impl
*);
46 typedef void (WINAPI
*destroy_fun_t
)(mutex_impl
*);
47 typedef void (WINAPI
*lock_exclusive_fun_t
)(mutex_impl
*);
48 typedef void (WINAPI
*lock_shared_fun_t
)(mutex_impl
*);
49 typedef void (WINAPI
*unlock_exclusive_fun_t
)(mutex_impl
*);
50 typedef void (WINAPI
*unlock_shared_fun_t
)(mutex_impl
*);
52 //! A complement stub function for InitializeSRWLock
53 void WINAPI
DeinitializeSRWLock(mutex_impl
*)
57 // The Boost.Thread-based implementation
58 void WINAPI
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
67 + ((sizeof(shared_mutex
) % BOOST_LOG_CPU_CACHE_LINE_SIZE
) != 0)
69 * BOOST_LOG_CPU_CACHE_LINE_SIZE
71 mtx
->p
= alignment::aligned_alloc(BOOST_LOG_CPU_CACHE_LINE_SIZE
, size
);
72 BOOST_ASSERT(mtx
->p
!= NULL
);
73 new (mtx
->p
) shared_mutex();
76 void WINAPI
DeinitializeSharedMutex(mutex_impl
* mtx
)
78 static_cast< shared_mutex
* >(mtx
->p
)->~shared_mutex();
79 alignment::aligned_free(mtx
->p
);
83 void WINAPI
ExclusiveLockSharedMutex(mutex_impl
* mtx
)
85 static_cast< shared_mutex
* >(mtx
->p
)->lock();
88 void WINAPI
SharedLockSharedMutex(mutex_impl
* mtx
)
90 static_cast< shared_mutex
* >(mtx
->p
)->lock_shared();
93 void WINAPI
ExclusiveUnlockSharedMutex(mutex_impl
* mtx
)
95 static_cast< shared_mutex
* >(mtx
->p
)->unlock();
98 void WINAPI
SharedUnlockSharedMutex(mutex_impl
* mtx
)
100 static_cast< shared_mutex
* >(mtx
->p
)->unlock_shared();
103 // Pointers to the actual implementation functions
104 init_fun_t g_pInitializeLWRWMutex
= NULL
;
105 destroy_fun_t g_pDestroyLWRWMutex
= NULL
;
106 lock_exclusive_fun_t g_pLockExclusiveLWRWMutex
= NULL
;
107 lock_shared_fun_t g_pLockSharedLWRWMutex
= NULL
;
108 unlock_exclusive_fun_t g_pUnlockExclusiveLWRWMutex
= NULL
;
109 unlock_shared_fun_t g_pUnlockSharedLWRWMutex
= NULL
;
111 //! The function dynamically initializes the implementation pointers
112 void init_light_rw_mutex_impl()
114 boost::winapi::HMODULE_ hKernel32
= boost::winapi::GetModuleHandleW(L
"kernel32.dll");
117 g_pInitializeLWRWMutex
=
118 (init_fun_t
)boost::winapi::get_proc_address(hKernel32
, "InitializeSRWLock");
119 if (g_pInitializeLWRWMutex
)
121 g_pLockExclusiveLWRWMutex
=
122 (lock_exclusive_fun_t
)boost::winapi::get_proc_address(hKernel32
, "AcquireSRWLockExclusive");
123 if (g_pLockExclusiveLWRWMutex
)
125 g_pUnlockExclusiveLWRWMutex
=
126 (unlock_exclusive_fun_t
)boost::winapi::get_proc_address(hKernel32
, "ReleaseSRWLockExclusive");
127 if (g_pUnlockExclusiveLWRWMutex
)
129 g_pLockSharedLWRWMutex
=
130 (lock_shared_fun_t
)boost::winapi::get_proc_address(hKernel32
, "AcquireSRWLockShared");
131 if (g_pLockSharedLWRWMutex
)
133 g_pUnlockSharedLWRWMutex
=
134 (unlock_shared_fun_t
)boost::winapi::get_proc_address(hKernel32
, "ReleaseSRWLockShared");
135 if (g_pUnlockSharedLWRWMutex
)
137 g_pDestroyLWRWMutex
= &DeinitializeSRWLock
;
146 // Current OS doesn't have support for SRWLOCK, use Boost.Thread instead
147 g_pInitializeLWRWMutex
= &InitializeSharedMutex
;
148 g_pDestroyLWRWMutex
= &DeinitializeSharedMutex
;
149 g_pLockExclusiveLWRWMutex
= &ExclusiveLockSharedMutex
;
150 g_pUnlockExclusiveLWRWMutex
= &ExclusiveUnlockSharedMutex
;
151 g_pLockSharedLWRWMutex
= &SharedLockSharedMutex
;
152 g_pUnlockSharedLWRWMutex
= &SharedUnlockSharedMutex
;
157 BOOST_LOG_API
light_rw_mutex::light_rw_mutex()
159 BOOST_LOG_ONCE_BLOCK()
161 init_light_rw_mutex_impl();
163 g_pInitializeLWRWMutex((mutex_impl
*)&m_Mutex
);
166 BOOST_LOG_API
light_rw_mutex::~light_rw_mutex()
168 g_pDestroyLWRWMutex((mutex_impl
*)&m_Mutex
);
171 BOOST_LOG_API
void light_rw_mutex::lock_shared()
173 g_pLockSharedLWRWMutex((mutex_impl
*)&m_Mutex
);
176 BOOST_LOG_API
void light_rw_mutex::unlock_shared()
178 g_pUnlockSharedLWRWMutex((mutex_impl
*)&m_Mutex
);
181 BOOST_LOG_API
void light_rw_mutex::lock()
183 g_pLockExclusiveLWRWMutex((mutex_impl
*)&m_Mutex
);
186 BOOST_LOG_API
void light_rw_mutex::unlock()
188 g_pUnlockExclusiveLWRWMutex((mutex_impl
*)&m_Mutex
);
193 BOOST_LOG_CLOSE_NAMESPACE
// namespace log
197 #include <boost/log/detail/footer.hpp>
199 #endif // !defined(BOOST_LOG_LWRWMUTEX_USE_PTHREAD) && !defined(BOOST_LOG_LWRWMUTEX_USE_SRWLOCK)
201 #endif // !defined(BOOST_LOG_NO_THREADS)