]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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/detail/winapi/basic_types.hpp> | |
31 | #include <boost/detail/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 (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*); | |
51 | ||
52 | //! A complement stub function for InitializeSRWLock | |
53 | void WINAPI DeinitializeSRWLock(mutex_impl*) | |
54 | { | |
55 | } | |
56 | ||
57 | // The Boost.Thread-based implementation | |
58 | void WINAPI 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 | |
67 | + ((sizeof(shared_mutex) % BOOST_LOG_CPU_CACHE_LINE_SIZE) != 0) | |
68 | ) | |
69 | * BOOST_LOG_CPU_CACHE_LINE_SIZE | |
70 | }; | |
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(); | |
74 | } | |
75 | ||
76 | void WINAPI DeinitializeSharedMutex(mutex_impl* mtx) | |
77 | { | |
78 | static_cast< shared_mutex* >(mtx->p)->~shared_mutex(); | |
79 | alignment::aligned_free(mtx->p); | |
80 | mtx->p = NULL; | |
81 | } | |
82 | ||
83 | void WINAPI ExclusiveLockSharedMutex(mutex_impl* mtx) | |
84 | { | |
85 | static_cast< shared_mutex* >(mtx->p)->lock(); | |
86 | } | |
87 | ||
88 | void WINAPI SharedLockSharedMutex(mutex_impl* mtx) | |
89 | { | |
90 | static_cast< shared_mutex* >(mtx->p)->lock_shared(); | |
91 | } | |
92 | ||
93 | void WINAPI ExclusiveUnlockSharedMutex(mutex_impl* mtx) | |
94 | { | |
95 | static_cast< shared_mutex* >(mtx->p)->unlock(); | |
96 | } | |
97 | ||
98 | void WINAPI SharedUnlockSharedMutex(mutex_impl* mtx) | |
99 | { | |
100 | static_cast< shared_mutex* >(mtx->p)->unlock_shared(); | |
101 | } | |
102 | ||
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; | |
110 | ||
111 | //! The function dynamically initializes the implementation pointers | |
112 | void init_light_rw_mutex_impl() | |
113 | { | |
114 | boost::detail::winapi::HMODULE_ hKernel32 = boost::detail::winapi::GetModuleHandleW(L"kernel32.dll"); | |
115 | if (hKernel32) | |
116 | { | |
117 | g_pInitializeLWRWMutex = | |
118 | (init_fun_t)boost::detail::winapi::get_proc_address(hKernel32, "InitializeSRWLock"); | |
119 | if (g_pInitializeLWRWMutex) | |
120 | { | |
121 | g_pLockExclusiveLWRWMutex = | |
122 | (lock_exclusive_fun_t)boost::detail::winapi::get_proc_address(hKernel32, "AcquireSRWLockExclusive"); | |
123 | if (g_pLockExclusiveLWRWMutex) | |
124 | { | |
125 | g_pUnlockExclusiveLWRWMutex = | |
126 | (unlock_exclusive_fun_t)boost::detail::winapi::get_proc_address(hKernel32, "ReleaseSRWLockExclusive"); | |
127 | if (g_pUnlockExclusiveLWRWMutex) | |
128 | { | |
129 | g_pLockSharedLWRWMutex = | |
130 | (lock_shared_fun_t)boost::detail::winapi::get_proc_address(hKernel32, "AcquireSRWLockShared"); | |
131 | if (g_pLockSharedLWRWMutex) | |
132 | { | |
133 | g_pUnlockSharedLWRWMutex = | |
134 | (unlock_shared_fun_t)boost::detail::winapi::get_proc_address(hKernel32, "ReleaseSRWLockShared"); | |
135 | if (g_pUnlockSharedLWRWMutex) | |
136 | { | |
137 | g_pDestroyLWRWMutex = &DeinitializeSRWLock; | |
138 | return; | |
139 | } | |
140 | } | |
141 | } | |
142 | } | |
143 | } | |
144 | } | |
145 | ||
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; | |
153 | } | |
154 | ||
155 | } // namespace | |
156 | ||
157 | BOOST_LOG_API light_rw_mutex::light_rw_mutex() | |
158 | { | |
159 | BOOST_LOG_ONCE_BLOCK() | |
160 | { | |
161 | init_light_rw_mutex_impl(); | |
162 | } | |
163 | g_pInitializeLWRWMutex((mutex_impl*)&m_Mutex); | |
164 | } | |
165 | ||
166 | BOOST_LOG_API light_rw_mutex::~light_rw_mutex() | |
167 | { | |
168 | g_pDestroyLWRWMutex((mutex_impl*)&m_Mutex); | |
169 | } | |
170 | ||
171 | BOOST_LOG_API void light_rw_mutex::lock_shared() | |
172 | { | |
173 | g_pLockSharedLWRWMutex((mutex_impl*)&m_Mutex); | |
174 | } | |
175 | ||
176 | BOOST_LOG_API void light_rw_mutex::unlock_shared() | |
177 | { | |
178 | g_pUnlockSharedLWRWMutex((mutex_impl*)&m_Mutex); | |
179 | } | |
180 | ||
181 | BOOST_LOG_API void light_rw_mutex::lock() | |
182 | { | |
183 | g_pLockExclusiveLWRWMutex((mutex_impl*)&m_Mutex); | |
184 | } | |
185 | ||
186 | BOOST_LOG_API void light_rw_mutex::unlock() | |
187 | { | |
188 | g_pUnlockExclusiveLWRWMutex((mutex_impl*)&m_Mutex); | |
189 | } | |
190 | ||
191 | } // namespace aux | |
192 | ||
193 | BOOST_LOG_CLOSE_NAMESPACE // namespace log | |
194 | ||
195 | } // namespace boost | |
196 | ||
197 | #include <boost/log/detail/footer.hpp> | |
198 | ||
199 | #endif // !defined(BOOST_LOG_LWRWMUTEX_USE_PTHREAD) && !defined(BOOST_LOG_LWRWMUTEX_USE_SRWLOCK) | |
200 | ||
201 | #endif // !defined(BOOST_LOG_NO_THREADS) |