2
0
mirror of https://github.com/boostorg/log.git synced 2026-02-09 11:12:38 +00:00
Files
log/src/light_rw_mutex.cpp
Andrey Semashev a31ec74e51 Make sure that Windows API version is consistent for all sources.
Include winapi/config.hpp as soon as possible; avoid including even
Boost.Config before it so that it doesn't set Windows API version
accidentally by including some third party header. In all source files,
include detail/config.hpp or detail/setup_config.hpp first thing.

Moved all WinAPI config macros to the Jamfile.v2 and removed
windows_version.hpp as it was no longer needed. Also enabled inclusion of
windows.h while compiling the library.

Removed auto-linking with psapi.lib and advapi32.lib as it was no longer
working after ecf3114. Added linking with advapi32.lib to Jamfile.v2.
2015-12-20 21:05:28 +03:00

202 lines
6.1 KiB
C++

/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file light_rw_mutex.cpp
* \author Andrey Semashev
* \date 19.06.2010
*
* \brief This header is the Boost.Log library implementation, see the library documentation
* at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
*/
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/light_rw_mutex.hpp>
#if !defined(BOOST_LOG_NO_THREADS)
#if !defined(BOOST_LOG_LWRWMUTEX_USE_PTHREAD) && !defined(BOOST_LOG_LWRWMUTEX_USE_SRWLOCK)
#include <cstddef>
#include <new>
#include <boost/assert.hpp>
#include <boost/align/aligned_alloc.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/log/utility/once_block.hpp>
#include <boost/detail/winapi/basic_types.hpp>
#include <boost/detail/winapi/dll.hpp>
#include <boost/log/detail/header.hpp>
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace aux {
BOOST_LOG_ANONYMOUS_NAMESPACE {
struct BOOST_LOG_MAY_ALIAS mutex_impl { void* p; }; // has the same layout as SRWLOCK and light_rw_mutex::m_Mutex
typedef void (WINAPI *init_fun_t)(mutex_impl*);
typedef void (WINAPI *destroy_fun_t)(mutex_impl*);
typedef void (WINAPI *lock_exclusive_fun_t)(mutex_impl*);
typedef void (WINAPI *lock_shared_fun_t)(mutex_impl*);
typedef void (WINAPI *unlock_exclusive_fun_t)(mutex_impl*);
typedef void (WINAPI *unlock_shared_fun_t)(mutex_impl*);
//! A complement stub function for InitializeSRWLock
void WINAPI DeinitializeSRWLock(mutex_impl*)
{
}
// The Boost.Thread-based implementation
void WINAPI InitializeSharedMutex(mutex_impl* mtx)
{
// To avoid cache line aliasing we do aligned memory allocation here
enum
{
// Allocation size is the minimum number of cache lines to accommodate shared_mutex
size =
(
sizeof(shared_mutex) / BOOST_LOG_CPU_CACHE_LINE_SIZE
+ ((sizeof(shared_mutex) % BOOST_LOG_CPU_CACHE_LINE_SIZE) != 0)
)
* BOOST_LOG_CPU_CACHE_LINE_SIZE
};
mtx->p = alignment::aligned_alloc(BOOST_LOG_CPU_CACHE_LINE_SIZE, size);
BOOST_ASSERT(mtx->p != NULL);
new (mtx->p) shared_mutex();
}
void WINAPI DeinitializeSharedMutex(mutex_impl* mtx)
{
static_cast< shared_mutex* >(mtx->p)->~shared_mutex();
alignment::aligned_free(mtx->p);
mtx->p = NULL;
}
void WINAPI ExclusiveLockSharedMutex(mutex_impl* mtx)
{
static_cast< shared_mutex* >(mtx->p)->lock();
}
void WINAPI SharedLockSharedMutex(mutex_impl* mtx)
{
static_cast< shared_mutex* >(mtx->p)->lock_shared();
}
void WINAPI ExclusiveUnlockSharedMutex(mutex_impl* mtx)
{
static_cast< shared_mutex* >(mtx->p)->unlock();
}
void WINAPI SharedUnlockSharedMutex(mutex_impl* mtx)
{
static_cast< shared_mutex* >(mtx->p)->unlock_shared();
}
// Pointers to the actual implementation functions
init_fun_t g_pInitializeLWRWMutex = NULL;
destroy_fun_t g_pDestroyLWRWMutex = NULL;
lock_exclusive_fun_t g_pLockExclusiveLWRWMutex = NULL;
lock_shared_fun_t g_pLockSharedLWRWMutex = NULL;
unlock_exclusive_fun_t g_pUnlockExclusiveLWRWMutex = NULL;
unlock_shared_fun_t g_pUnlockSharedLWRWMutex = NULL;
//! The function dynamically initializes the implementation pointers
void init_light_rw_mutex_impl()
{
boost::detail::winapi::HMODULE_ hKernel32 = boost::detail::winapi::GetModuleHandleW(L"kernel32.dll");
if (hKernel32)
{
g_pInitializeLWRWMutex =
(init_fun_t)boost::detail::winapi::get_proc_address(hKernel32, "InitializeSRWLock");
if (g_pInitializeLWRWMutex)
{
g_pLockExclusiveLWRWMutex =
(lock_exclusive_fun_t)boost::detail::winapi::get_proc_address(hKernel32, "AcquireSRWLockExclusive");
if (g_pLockExclusiveLWRWMutex)
{
g_pUnlockExclusiveLWRWMutex =
(unlock_exclusive_fun_t)boost::detail::winapi::get_proc_address(hKernel32, "ReleaseSRWLockExclusive");
if (g_pUnlockExclusiveLWRWMutex)
{
g_pLockSharedLWRWMutex =
(lock_shared_fun_t)boost::detail::winapi::get_proc_address(hKernel32, "AcquireSRWLockShared");
if (g_pLockSharedLWRWMutex)
{
g_pUnlockSharedLWRWMutex =
(unlock_shared_fun_t)boost::detail::winapi::get_proc_address(hKernel32, "ReleaseSRWLockShared");
if (g_pUnlockSharedLWRWMutex)
{
g_pDestroyLWRWMutex = &DeinitializeSRWLock;
return;
}
}
}
}
}
}
// Current OS doesn't have support for SRWLOCK, use Boost.Thread instead
g_pInitializeLWRWMutex = &InitializeSharedMutex;
g_pDestroyLWRWMutex = &DeinitializeSharedMutex;
g_pLockExclusiveLWRWMutex = &ExclusiveLockSharedMutex;
g_pUnlockExclusiveLWRWMutex = &ExclusiveUnlockSharedMutex;
g_pLockSharedLWRWMutex = &SharedLockSharedMutex;
g_pUnlockSharedLWRWMutex = &SharedUnlockSharedMutex;
}
} // namespace
BOOST_LOG_API light_rw_mutex::light_rw_mutex()
{
BOOST_LOG_ONCE_BLOCK()
{
init_light_rw_mutex_impl();
}
g_pInitializeLWRWMutex((mutex_impl*)&m_Mutex);
}
BOOST_LOG_API light_rw_mutex::~light_rw_mutex()
{
g_pDestroyLWRWMutex((mutex_impl*)&m_Mutex);
}
BOOST_LOG_API void light_rw_mutex::lock_shared()
{
g_pLockSharedLWRWMutex((mutex_impl*)&m_Mutex);
}
BOOST_LOG_API void light_rw_mutex::unlock_shared()
{
g_pUnlockSharedLWRWMutex((mutex_impl*)&m_Mutex);
}
BOOST_LOG_API void light_rw_mutex::lock()
{
g_pLockExclusiveLWRWMutex((mutex_impl*)&m_Mutex);
}
BOOST_LOG_API void light_rw_mutex::unlock()
{
g_pUnlockExclusiveLWRWMutex((mutex_impl*)&m_Mutex);
}
} // namespace aux
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // !defined(BOOST_LOG_LWRWMUTEX_USE_PTHREAD) && !defined(BOOST_LOG_LWRWMUTEX_USE_SRWLOCK)
#endif // !defined(BOOST_LOG_NO_THREADS)