mirror of
https://github.com/boostorg/log.git
synced 2026-02-03 09:12:19 +00:00
293 lines
7.3 KiB
C++
293 lines
7.3 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 thread_specific.cpp
|
|
* \author Andrey Semashev
|
|
* \date 01.03.2008
|
|
*
|
|
* \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 <string>
|
|
#include <stdexcept>
|
|
#include <boost/log/exceptions.hpp>
|
|
#include <boost/log/detail/thread_specific.hpp>
|
|
|
|
#if !defined(BOOST_LOG_NO_THREADS)
|
|
|
|
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
|
|
|
#include <windows.h>
|
|
#include <boost/system/error_code.hpp>
|
|
#include <boost/log/detail/header.hpp>
|
|
|
|
namespace boost {
|
|
|
|
BOOST_LOG_OPEN_NAMESPACE
|
|
|
|
namespace aux {
|
|
|
|
thread_specific_base::thread_specific_base()
|
|
{
|
|
m_Key = TlsAlloc();
|
|
if (BOOST_UNLIKELY(m_Key == TLS_OUT_OF_INDEXES))
|
|
{
|
|
BOOST_LOG_THROW_DESCR_PARAMS(system_error, "TLS capacity depleted", (boost::system::errc::not_enough_memory));
|
|
}
|
|
}
|
|
|
|
thread_specific_base::~thread_specific_base()
|
|
{
|
|
TlsFree(m_Key);
|
|
}
|
|
|
|
void* thread_specific_base::get_content() const
|
|
{
|
|
return TlsGetValue(m_Key);
|
|
}
|
|
|
|
void thread_specific_base::set_content(void* value) const
|
|
{
|
|
TlsSetValue(m_Key, value);
|
|
}
|
|
|
|
} // namespace aux
|
|
|
|
BOOST_LOG_CLOSE_NAMESPACE // namespace log
|
|
|
|
} // namespace boost
|
|
|
|
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
|
|
|
|
#include <cstddef>
|
|
#include <cstring>
|
|
#include <pthread.h>
|
|
#include <boost/cstdint.hpp>
|
|
#include <boost/mpl/if.hpp>
|
|
#include <boost/type_traits/is_integral.hpp>
|
|
#include <boost/type_traits/is_signed.hpp>
|
|
#include <boost/log/detail/header.hpp>
|
|
|
|
namespace boost {
|
|
|
|
BOOST_LOG_OPEN_NAMESPACE
|
|
|
|
namespace aux {
|
|
|
|
BOOST_LOG_ANONYMOUS_NAMESPACE {
|
|
|
|
//! Some portability magic to detect how to store the TLS key
|
|
template< typename KeyT, bool IsStoreableV = sizeof(KeyT) <= sizeof(void*), bool IsIntegralV = boost::is_integral< KeyT >::value >
|
|
struct pthread_key_traits
|
|
{
|
|
typedef KeyT pthread_key_type;
|
|
|
|
static void allocate(void*& stg)
|
|
{
|
|
pthread_key_type* pkey = new pthread_key_type();
|
|
const int res = pthread_key_create(pkey, NULL);
|
|
if (BOOST_UNLIKELY(res != 0))
|
|
{
|
|
delete pkey;
|
|
BOOST_LOG_THROW_DESCR_PARAMS(system_error, "TLS capacity depleted", (res));
|
|
}
|
|
stg = pkey;
|
|
}
|
|
|
|
static void deallocate(void* stg)
|
|
{
|
|
pthread_key_type* pkey = static_cast< pthread_key_type* >(stg);
|
|
pthread_key_delete(*pkey);
|
|
delete pkey;
|
|
}
|
|
|
|
static void set_value(void* stg, void* value)
|
|
{
|
|
const int res = pthread_setspecific(*static_cast< pthread_key_type* >(stg), value);
|
|
if (BOOST_UNLIKELY(res != 0))
|
|
{
|
|
BOOST_LOG_THROW_DESCR_PARAMS(system_error, "Failed to set TLS value", (res));
|
|
}
|
|
}
|
|
|
|
static void* get_value(void* stg)
|
|
{
|
|
return pthread_getspecific(*static_cast< pthread_key_type* >(stg));
|
|
}
|
|
};
|
|
|
|
template< typename KeyT >
|
|
struct pthread_key_traits< KeyT, true, true >
|
|
{
|
|
typedef KeyT pthread_key_type;
|
|
|
|
#if defined(BOOST_HAS_INTPTR_T)
|
|
typedef typename mpl::if_c<
|
|
boost::is_signed< pthread_key_type >::value,
|
|
intptr_t,
|
|
uintptr_t
|
|
>::type intptr_type;
|
|
#else
|
|
typedef typename mpl::if_c<
|
|
boost::is_signed< pthread_key_type >::value,
|
|
std::ptrdiff_t,
|
|
std::size_t
|
|
>::type intptr_type;
|
|
#endif
|
|
|
|
static void allocate(void*& stg)
|
|
{
|
|
pthread_key_type key;
|
|
const int res = pthread_key_create(&key, NULL);
|
|
if (BOOST_UNLIKELY(res != 0))
|
|
{
|
|
BOOST_LOG_THROW_DESCR_PARAMS(system_error, "TLS capacity depleted", (res));
|
|
}
|
|
stg = (void*)(intptr_type)key;
|
|
}
|
|
|
|
static void deallocate(void* stg)
|
|
{
|
|
pthread_key_delete((pthread_key_type)(intptr_type)stg);
|
|
}
|
|
|
|
static void set_value(void* stg, void* value)
|
|
{
|
|
const int res = pthread_setspecific((pthread_key_type)(intptr_type)stg, value);
|
|
if (BOOST_UNLIKELY(res != 0))
|
|
{
|
|
BOOST_LOG_THROW_DESCR_PARAMS(system_error, "Failed to set TLS value", (res));
|
|
}
|
|
}
|
|
|
|
static void* get_value(void* stg)
|
|
{
|
|
return pthread_getspecific((pthread_key_type)(intptr_type)stg);
|
|
}
|
|
};
|
|
|
|
template< typename KeyT >
|
|
struct pthread_key_traits< KeyT, true, false >
|
|
{
|
|
typedef KeyT pthread_key_type;
|
|
|
|
static void allocate(void*& stg)
|
|
{
|
|
pthread_key_type key;
|
|
const int res = pthread_key_create(&key, NULL);
|
|
if (BOOST_UNLIKELY(res != 0))
|
|
{
|
|
BOOST_LOG_THROW_DESCR_PARAMS(system_error, "TLS capacity depleted", (res));
|
|
}
|
|
std::memset(&stg, 0, sizeof(stg));
|
|
std::memcpy(&stg, &key, sizeof(pthread_key_type));
|
|
}
|
|
|
|
static void deallocate(void* stg)
|
|
{
|
|
pthread_key_type key;
|
|
std::memcpy(&key, &stg, sizeof(pthread_key_type));
|
|
pthread_key_delete(key);
|
|
}
|
|
|
|
static void set_value(void* stg, void* value)
|
|
{
|
|
pthread_key_type key;
|
|
std::memcpy(&key, &stg, sizeof(pthread_key_type));
|
|
const int res = pthread_setspecific(key, value);
|
|
if (BOOST_UNLIKELY(res != 0))
|
|
{
|
|
BOOST_LOG_THROW_DESCR_PARAMS(system_error, "Failed to set TLS value", (res));
|
|
}
|
|
}
|
|
|
|
static void* get_value(void* stg)
|
|
{
|
|
pthread_key_type key;
|
|
std::memcpy(&key, &stg, sizeof(pthread_key_type));
|
|
return pthread_getspecific(key);
|
|
}
|
|
};
|
|
|
|
template< typename KeyT >
|
|
struct pthread_key_traits< KeyT*, true, false >
|
|
{
|
|
typedef KeyT* pthread_key_type;
|
|
|
|
static void allocate(void*& stg)
|
|
{
|
|
pthread_key_type key = NULL;
|
|
const int res = pthread_key_create(&key, NULL);
|
|
if (BOOST_UNLIKELY(res != 0))
|
|
{
|
|
BOOST_LOG_THROW_DESCR_PARAMS(system_error, "TLS capacity depleted", (res));
|
|
}
|
|
stg = static_cast< void* >(key);
|
|
}
|
|
|
|
static void deallocate(void* stg)
|
|
{
|
|
pthread_key_delete(static_cast< pthread_key_type >(stg));
|
|
}
|
|
|
|
static void set_value(void* stg, void* value)
|
|
{
|
|
const int res = pthread_setspecific(static_cast< pthread_key_type >(stg), value);
|
|
if (BOOST_UNLIKELY(res != 0))
|
|
{
|
|
BOOST_LOG_THROW_DESCR_PARAMS(system_error, "Failed to set TLS value", (res));
|
|
}
|
|
}
|
|
|
|
static void* get_value(void* stg)
|
|
{
|
|
return pthread_getspecific(static_cast< pthread_key_type >(stg));
|
|
}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
thread_specific_base::thread_specific_base()
|
|
{
|
|
typedef pthread_key_traits< pthread_key_t > traits_t;
|
|
traits_t::allocate(m_Key);
|
|
}
|
|
|
|
thread_specific_base::~thread_specific_base()
|
|
{
|
|
typedef pthread_key_traits< pthread_key_t > traits_t;
|
|
traits_t::deallocate(m_Key);
|
|
}
|
|
|
|
void* thread_specific_base::get_content() const
|
|
{
|
|
typedef pthread_key_traits< pthread_key_t > traits_t;
|
|
return traits_t::get_value(m_Key);
|
|
}
|
|
|
|
void thread_specific_base::set_content(void* value) const
|
|
{
|
|
typedef pthread_key_traits< pthread_key_t > traits_t;
|
|
traits_t::set_value(m_Key, value);
|
|
}
|
|
|
|
} // namespace aux
|
|
|
|
BOOST_LOG_CLOSE_NAMESPACE // namespace log
|
|
|
|
} // namespace boost
|
|
|
|
#else
|
|
#error Boost.Log: unsupported threading API
|
|
#endif
|
|
|
|
#include <boost/log/detail/footer.hpp>
|
|
|
|
#endif // !defined(BOOST_LOG_NO_THREADS)
|