mirror of
https://github.com/boostorg/log.git
synced 2026-02-09 11:12:38 +00:00
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.
202 lines
6.1 KiB
C++
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)
|