2
0
mirror of https://github.com/boostorg/log.git synced 2026-01-28 07:12:23 +00:00
Files
log/src/named_scope.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

314 lines
9.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 named_scope.cpp
* \author Andrey Semashev
* \date 24.06.2007
*
* \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 <utility>
#include <algorithm>
#include <boost/type_index.hpp>
#include <boost/optional/optional.hpp>
#include <boost/log/attributes/attribute.hpp>
#include <boost/log/attributes/attribute_value.hpp>
#include <boost/log/attributes/named_scope.hpp>
#include <boost/log/utility/type_dispatch/type_dispatcher.hpp>
#include <boost/log/detail/singleton.hpp>
#if !defined(BOOST_LOG_NO_THREADS)
#include <boost/thread/tss.hpp>
#endif
#include "unique_ptr.hpp"
#include <boost/log/detail/header.hpp>
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace attributes {
BOOST_LOG_ANONYMOUS_NAMESPACE {
//! Actual implementation of the named scope list
class writeable_named_scope_list :
public named_scope_list
{
//! Base type
typedef named_scope_list base_type;
public:
//! Const reference type
typedef base_type::const_reference const_reference;
public:
//! The method pushes the scope to the back of the list
BOOST_FORCEINLINE void push_back(const_reference entry) BOOST_NOEXCEPT
{
aux::named_scope_list_node* top = this->m_RootNode._m_pPrev;
entry._m_pPrev = top;
entry._m_pNext = &this->m_RootNode;
BOOST_LOG_ASSUME(&entry != 0);
this->m_RootNode._m_pPrev = top->_m_pNext =
const_cast< aux::named_scope_list_node* >(
static_cast< const aux::named_scope_list_node* >(&entry));
++this->m_Size;
}
//! The method removes the top scope entry from the list
BOOST_FORCEINLINE void pop_back() BOOST_NOEXCEPT
{
aux::named_scope_list_node* top = this->m_RootNode._m_pPrev;
top->_m_pPrev->_m_pNext = top->_m_pNext;
top->_m_pNext->_m_pPrev = top->_m_pPrev;
--this->m_Size;
}
};
//! Named scope attribute value
class named_scope_value :
public attribute_value::impl
{
//! Scope names stack
typedef named_scope_list scope_stack;
//! Pointer to the actual scope value
scope_stack* m_pValue;
//! A thread-independent value
optional< scope_stack > m_DetachedValue;
public:
//! Constructor
explicit named_scope_value(scope_stack* p) : m_pValue(p) {}
//! The method dispatches the value to the given object. It returns true if the
//! object was capable to consume the real attribute value type and false otherwise.
bool dispatch(type_dispatcher& dispatcher)
{
type_dispatcher::callback< scope_stack > callback =
dispatcher.get_callback< scope_stack >();
if (callback)
{
callback(*m_pValue);
return true;
}
else
return false;
}
/*!
* \return The attribute value type
*/
typeindex::type_index get_type() const { return typeindex::type_id< scope_stack >(); }
//! The method is called when the attribute value is passed to another thread (e.g.
//! in case of asynchronous logging). The value should ensure it properly owns all thread-specific data.
intrusive_ptr< attribute_value::impl > detach_from_thread()
{
if (!m_DetachedValue)
{
m_DetachedValue = *m_pValue;
m_pValue = m_DetachedValue.get_ptr();
}
return this;
}
};
} // namespace
//! Named scope attribute implementation
struct BOOST_SYMBOL_VISIBLE named_scope::impl :
public attribute::impl,
public log::aux::singleton<
impl,
intrusive_ptr< impl >
>
{
//! Singleton base type
typedef log::aux::singleton<
impl,
intrusive_ptr< impl >
> singleton_base_type;
//! Writable scope list type
typedef writeable_named_scope_list scope_list;
#if !defined(BOOST_LOG_NO_THREADS)
//! Pointer to the thread-specific scope stack
thread_specific_ptr< scope_list > pScopes;
#if defined(BOOST_LOG_USE_COMPILER_TLS)
//! Cached pointer to the thread-specific scope stack
static BOOST_LOG_TLS scope_list* pScopesCache;
#endif
#else
//! Pointer to the scope stack
log::aux::unique_ptr< scope_list > pScopes;
#endif
//! The method returns current thread scope stack
scope_list& get_scope_list()
{
#if defined(BOOST_LOG_USE_COMPILER_TLS)
scope_list* p = pScopesCache;
#else
scope_list* p = pScopes.get();
#endif
if (!p)
{
log::aux::unique_ptr< scope_list > pNew(new scope_list());
pScopes.reset(pNew.get());
#if defined(BOOST_LOG_USE_COMPILER_TLS)
pScopesCache = p = pNew.release();
#else
p = pNew.release();
#endif
}
return *p;
}
//! Instance initializer
static void init_instance()
{
singleton_base_type::get_instance().reset(new impl());
}
//! The method returns the actual attribute value. It must not return NULL.
attribute_value get_value()
{
return attribute_value(new named_scope_value(&get_scope_list()));
}
private:
impl() {}
};
#if defined(BOOST_LOG_USE_COMPILER_TLS)
//! Cached pointer to the thread-specific scope stack
BOOST_LOG_TLS named_scope::impl::scope_list*
named_scope::impl::pScopesCache = NULL;
#endif // defined(BOOST_LOG_USE_COMPILER_TLS)
//! Copy constructor
BOOST_LOG_API named_scope_list::named_scope_list(named_scope_list const& that) :
allocator_type(static_cast< allocator_type const& >(that)),
m_Size(that.size()),
m_fNeedToDeallocate(!that.empty())
{
if (m_Size > 0)
{
// Copy the container contents
pointer p = allocator_type::allocate(that.size());
aux::named_scope_list_node* prev = &m_RootNode;
for (const_iterator src = that.begin(), end = that.end(); src != end; ++src, ++p)
{
allocator_type::construct(p, *src); // won't throw
p->_m_pPrev = prev;
prev->_m_pNext = p;
prev = p;
}
m_RootNode._m_pPrev = prev;
prev->_m_pNext = &m_RootNode;
}
}
//! Destructor
BOOST_LOG_API named_scope_list::~named_scope_list()
{
if (m_fNeedToDeallocate)
{
iterator it(m_RootNode._m_pNext);
iterator end(&m_RootNode);
while (it != end)
allocator_type::destroy(&*(it++));
allocator_type::deallocate(static_cast< pointer >(m_RootNode._m_pNext), m_Size);
}
}
//! Swaps two instances of the container
BOOST_LOG_API void named_scope_list::swap(named_scope_list& that)
{
if (!this->empty())
{
if (!that.empty())
{
// both containers are not empty
std::swap(m_RootNode._m_pNext->_m_pPrev, that.m_RootNode._m_pNext->_m_pPrev);
std::swap(m_RootNode._m_pPrev->_m_pNext, that.m_RootNode._m_pPrev->_m_pNext);
std::swap(m_RootNode, that.m_RootNode);
std::swap(m_Size, that.m_Size);
std::swap(m_fNeedToDeallocate, that.m_fNeedToDeallocate);
}
else
{
// this is not empty
m_RootNode._m_pNext->_m_pPrev = m_RootNode._m_pPrev->_m_pNext = &that.m_RootNode;
that.m_RootNode = m_RootNode;
m_RootNode._m_pNext = m_RootNode._m_pPrev = &m_RootNode;
std::swap(m_Size, that.m_Size);
std::swap(m_fNeedToDeallocate, that.m_fNeedToDeallocate);
}
}
else if (!that.empty())
{
// that is not empty
that.m_RootNode._m_pNext->_m_pPrev = that.m_RootNode._m_pPrev->_m_pNext = &m_RootNode;
m_RootNode = that.m_RootNode;
that.m_RootNode._m_pNext = that.m_RootNode._m_pPrev = &that.m_RootNode;
std::swap(m_Size, that.m_Size);
std::swap(m_fNeedToDeallocate, that.m_fNeedToDeallocate);
}
}
//! Constructor
named_scope::named_scope() :
attribute(impl::instance)
{
}
//! Constructor for casting support
named_scope::named_scope(cast_source const& source) :
attribute(source.as< impl >())
{
}
//! The method pushes the scope to the stack
void named_scope::push_scope(scope_entry const& entry) BOOST_NOEXCEPT
{
impl::scope_list& s = impl::instance->get_scope_list();
s.push_back(entry);
}
//! The method pops the top scope
void named_scope::pop_scope() BOOST_NOEXCEPT
{
impl::scope_list& s = impl::instance->get_scope_list();
s.pop_back();
}
//! Returns the current thread's scope stack
named_scope::value_type const& named_scope::get_scopes()
{
return impl::instance->get_scope_list();
}
} // namespace attributes
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>