]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/log/src/windows/light_rw_mutex.cpp
885dc175204d61fb1afdfc58e8c9158bc9a442d5
[ceph.git] / ceph / src / boost / libs / log / src / windows / light_rw_mutex.cpp
1 /*
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)
6 */
7 /*!
8 * \file light_rw_mutex.cpp
9 * \author Andrey Semashev
10 * \date 19.06.2010
11 *
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.
14 */
15
16 #include <boost/log/detail/config.hpp>
17 #include <boost/log/detail/light_rw_mutex.hpp>
18
19 #if !defined(BOOST_LOG_NO_THREADS)
20
21 #if !defined(BOOST_LOG_LWRWMUTEX_USE_PTHREAD) && !defined(BOOST_LOG_LWRWMUTEX_USE_SRWLOCK)
22
23 #include <cstddef>
24 #include <new>
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>
29
30 #include <boost/winapi/basic_types.hpp>
31 #include <boost/winapi/dll.hpp>
32
33 #include <boost/log/detail/header.hpp>
34
35 namespace boost {
36
37 BOOST_LOG_OPEN_NAMESPACE
38
39 namespace aux {
40
41 BOOST_LOG_ANONYMOUS_NAMESPACE {
42
43 struct BOOST_LOG_MAY_ALIAS mutex_impl { void* p; }; // has the same layout as SRWLOCK and light_rw_mutex::m_Mutex
44
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*);
51
52 //! A complement stub function for InitializeSRWLock
53 void BOOST_WINAPI_WINAPI_CC DeinitializeSRWLock(mutex_impl*)
54 {
55 }
56
57 // The Boost.Thread-based implementation
58 void BOOST_WINAPI_WINAPI_CC InitializeSharedMutex(mutex_impl* mtx)
59 {
60 // To avoid cache line aliasing we do aligned memory allocation here
61 enum
62 {
63 // Allocation size is the minimum number of cache lines to accommodate shared_mutex
64 size =
65 (
66 (sizeof(shared_mutex) + BOOST_LOG_CPU_CACHE_LINE_SIZE - 1u) / BOOST_LOG_CPU_CACHE_LINE_SIZE
67 )
68 * BOOST_LOG_CPU_CACHE_LINE_SIZE
69 };
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();
73 }
74
75 void BOOST_WINAPI_WINAPI_CC DeinitializeSharedMutex(mutex_impl* mtx)
76 {
77 static_cast< shared_mutex* >(mtx->p)->~shared_mutex();
78 alignment::aligned_free(mtx->p);
79 mtx->p = NULL;
80 }
81
82 void BOOST_WINAPI_WINAPI_CC ExclusiveLockSharedMutex(mutex_impl* mtx)
83 {
84 static_cast< shared_mutex* >(mtx->p)->lock();
85 }
86
87 void BOOST_WINAPI_WINAPI_CC SharedLockSharedMutex(mutex_impl* mtx)
88 {
89 static_cast< shared_mutex* >(mtx->p)->lock_shared();
90 }
91
92 void BOOST_WINAPI_WINAPI_CC ExclusiveUnlockSharedMutex(mutex_impl* mtx)
93 {
94 static_cast< shared_mutex* >(mtx->p)->unlock();
95 }
96
97 void BOOST_WINAPI_WINAPI_CC SharedUnlockSharedMutex(mutex_impl* mtx)
98 {
99 static_cast< shared_mutex* >(mtx->p)->unlock_shared();
100 }
101
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;
109
110 //! The function dynamically initializes the implementation pointers
111 void init_light_rw_mutex_impl()
112 {
113 boost::winapi::HMODULE_ hKernel32 = boost::winapi::GetModuleHandleW(L"kernel32.dll");
114 if (hKernel32)
115 {
116 g_pInitializeLWRWMutex =
117 (init_fun_t)boost::winapi::get_proc_address(hKernel32, "InitializeSRWLock");
118 if (g_pInitializeLWRWMutex)
119 {
120 g_pLockExclusiveLWRWMutex =
121 (lock_exclusive_fun_t)boost::winapi::get_proc_address(hKernel32, "AcquireSRWLockExclusive");
122 if (g_pLockExclusiveLWRWMutex)
123 {
124 g_pUnlockExclusiveLWRWMutex =
125 (unlock_exclusive_fun_t)boost::winapi::get_proc_address(hKernel32, "ReleaseSRWLockExclusive");
126 if (g_pUnlockExclusiveLWRWMutex)
127 {
128 g_pLockSharedLWRWMutex =
129 (lock_shared_fun_t)boost::winapi::get_proc_address(hKernel32, "AcquireSRWLockShared");
130 if (g_pLockSharedLWRWMutex)
131 {
132 g_pUnlockSharedLWRWMutex =
133 (unlock_shared_fun_t)boost::winapi::get_proc_address(hKernel32, "ReleaseSRWLockShared");
134 if (g_pUnlockSharedLWRWMutex)
135 {
136 g_pDestroyLWRWMutex = &DeinitializeSRWLock;
137 return;
138 }
139 }
140 }
141 }
142 }
143 }
144
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;
152 }
153
154 } // namespace
155
156 BOOST_LOG_API light_rw_mutex::light_rw_mutex()
157 {
158 BOOST_LOG_ONCE_BLOCK()
159 {
160 init_light_rw_mutex_impl();
161 }
162 g_pInitializeLWRWMutex((mutex_impl*)&m_Mutex);
163 }
164
165 BOOST_LOG_API light_rw_mutex::~light_rw_mutex()
166 {
167 g_pDestroyLWRWMutex((mutex_impl*)&m_Mutex);
168 }
169
170 BOOST_LOG_API void light_rw_mutex::lock_shared()
171 {
172 g_pLockSharedLWRWMutex((mutex_impl*)&m_Mutex);
173 }
174
175 BOOST_LOG_API void light_rw_mutex::unlock_shared()
176 {
177 g_pUnlockSharedLWRWMutex((mutex_impl*)&m_Mutex);
178 }
179
180 BOOST_LOG_API void light_rw_mutex::lock()
181 {
182 g_pLockExclusiveLWRWMutex((mutex_impl*)&m_Mutex);
183 }
184
185 BOOST_LOG_API void light_rw_mutex::unlock()
186 {
187 g_pUnlockExclusiveLWRWMutex((mutex_impl*)&m_Mutex);
188 }
189
190 } // namespace aux
191
192 BOOST_LOG_CLOSE_NAMESPACE // namespace log
193
194 } // namespace boost
195
196 #include <boost/log/detail/footer.hpp>
197
198 #endif // !defined(BOOST_LOG_LWRWMUTEX_USE_PTHREAD) && !defined(BOOST_LOG_LWRWMUTEX_USE_SRWLOCK)
199
200 #endif // !defined(BOOST_LOG_NO_THREADS)