<commit_before>/*
 *          Copyright <NAME> 2007 - 2013.
 * 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   core.cpp
 * \author <NAME>
 * \date   19.04.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 <cstddef>
#include <new>
#include <memory>
#include <vector>
#include <algorithm>
#include <boost/cstdint.hpp>
#include <boost/assert.hpp>
#include <boost/smart_ptr/weak_ptr.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/move/core.hpp>
#include <boost/move/utility.hpp>
#include <boost/log/core/core.hpp>
#include <boost/log/core/record.hpp>
#include <boost/log/core/record_view.hpp>
#include <boost/log/sinks/sink.hpp>
#include <boost/log/attributes/attribute_value_set.hpp>
#include <boost/log/detail/singleton.hpp>
#if !defined(BOOST_LOG_NO_THREADS)
#include <boost/thread/tss.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/log/detail/locks.hpp>
#include <boost/log/detail/light_rw_mutex.hpp>
#endif
#include "default_sink.hpp"
#include "stateless_allocator.hpp"
#include "alignment_gap_between.hpp"
#include <boost/log/detail/header.hpp>

namespace boost {

BOOST_LOG_OPEN_NAMESPACE

//! Private record data information, with core-specific structures
struct record_view::private_data :
    public public_data
{
    //! Underlying memory allocator
    typedef boost::log::aux::stateless_allocator< char > stateless_allocator;
    //! Sink pointer type
    typedef weak_ptr< sinks::sink > sink_ptr;
    //! Iterator range with pointers to the accepting sinks
    typedef iterator_range< sink_ptr* > sink_list;

private:
    //! Number of sinks accepting the record
    uint32_t m_accepting_sink_count;
    //! Maximum number of sinks accepting the record
    const uint32_t m_accepting_sink_capacity;
    //! The flag indicates that the record has to be detached from the current thread
    bool m_detach_from_thread_needed;

private:
    //! Initializing constructor
    private_data(BOOST_RV_REF(attribute_value_set) values, uint32_t capacity) :
        public_data(boost::move(values)),
        m_accepting_sink_count(0),
        m_accepting_sink_capacity(capacity),
        m_detach_from_thread_needed(false)
    {
    }

public:
    //! Creates the object with the specified capacity
    static private_data* create(BOOST_RV_REF(attribute_value_set) values, uint32_t capacity)
    {
        private_data* p = reinterpret_cast< private_data* >(stateless_allocator().allocate
        (
            sizeof(private_data) +
            boost::log::aux::alignment_gap_between< private_data, sink_ptr >::value +
            capacity * sizeof(sink_ptr)
        ));
        new (p) private_data(boost::move(values), capacity);
        return p;
    }

    //! Destroys the object and frees the underlying storage
    void destroy() BOOST_NOEXCEPT
    {
        sink_list s = get_accepting_sinks();
        for (sink_list::iterator it = s.begin(), end = s.end(); it != end; ++it)
        {
            it->~sink_ptr();
        }

        const uint32_t capacity = m_accepting_sink_capacity;
        this->~private_data();

        stateless_allocator().deallocate
        (
            reinterpret_cast< stateless_allocator::pointer >(this),
            sizeof(private_data) +
                boost::log::aux::alignment_gap_between< private_data, sink_ptr >::value +
                capacity * sizeof(sink_ptr)
        );
    }

    //! Returns iterator range with the pointers to the accepting sinks
    sink_list get_accepting_sinks() BOOST_NOEXCEPT
    {
        sink_ptr* p = begin();
        return sink_list(p, p + m_accepting_sink_count);
    }

    //! Adds an accepting sink
    void push_back_accepting_sink(shared_ptr< sinks::sink > const& sink)
    {
        BOOST_ASSERT(m_accepting_sink_count < m_accepting_sink_capacity);
        sink_ptr* p = begin() + m_accepting_sink_count;
        new (p) sink_ptr(sink);
        ++m_accepting_sink_count;
        m_detach_from_thread_needed |= sink->is_cross_thread();
    }

    //! Returns the number of accepting sinks
    uint32_t accepting_sink_count() const BOOST_NOEXCEPT { return m_accepting_sink_count; }

    //! Returns the flag indicating whether it is needed to detach the record from the current thread
    bool is_detach_from_thread_needed() const BOOST_NOEXCEPT { return m_detach_from_thread_needed; }

    BOOST_DELETED_FUNCTION(private_data(private_data const&))
    BOOST_DELETED_FUNCTION(private_data& operator= (private_data const&))

private:
    //! Returns a pointer to the first accepting sink
    sink_ptr* begin() BOOST_NOEXCEPT
    {
        return reinterpret_cast< sink_ptr* >
        (
            reinterpret_cast< char* >(this) +
                sizeof(private_data) +
                boost::log::aux::alignment_gap_between< private_data, sink_ptr >::value
        );
    }
};

//! Destructor
BOOST_LOG_API void record_view::public_data::destroy(const public_data* p) BOOST_NOEXCEPT
{
    const_cast< private_data* >(static_cast< const private_data* >(p))->destroy();
}

//! The function ensures that the log record does not depend on any thread-specific data.
BOOST_LOG_API record_view record::lock()
{
    BOOST_ASSERT(m_impl != NULL);

    record_view::private_data* const impl = static_cast< record_view::private_data* >(m_impl);
    if (impl->is_detach_from_thread_needed())
    {
        attribute_value_set::const_iterator
            it = impl->m_attribute_values.begin(),
            end = impl->m_attribute_values.end();
        for (; it != end; ++it)
        {
            // Yep, a bit hackish. I'll need a better backdoor to do it gracefully.
            const_cast< attribute_value_set::mapped_type& >(it->second).detach_from_thread();
        }
    }

    // Move the implementation to the view
    m_impl = NULL;
    return record_view(impl);
}

//! Logging system implementation
struct core::implementation :
    public log::aux::lazy_singleton<
        implementation,
        core_ptr
    >
{
public:
    //! Base type of singleton holder
    typedef log::aux::lazy_singleton<
        implementation,
        core_ptr
    > base_type;

#if !defined(BOOST_LOG_NO_THREADS)
    //! Read lock type
    typedef log::aux::shared_lock_guard< log::aux::light_rw_mutex > scoped_read_lock;
    //! Write lock type
    typedef log::aux::exclusive_lock_guard< log::aux::light_rw_mutex > scoped_write_lock;
#endif

    //! Sinks container type
    typedef std::vector< shared_ptr< sinks::sink > > sink_list;

    //! Thread-specific data
    struct thread_data
    {
        //! Thread-specific attribute set
        attribute_set m_thread_attributes;
    };

public:
#if !defined(BOOST_LOG_NO_THREADS)
    //! Synchronization mutex
    log::aux::light_rw_mutex m_mutex;
#endif

    //! List of sinks involved into output
    sink_list m_sinks;
    //! Default sink
    const shared_ptr< sinks::sink > m_default_sink;

    //! Global attribute set
    attribute_set m_global_attributes;
#if !defined(BOOST_LOG_NO_THREADS)
    //! Thread-specific data
    thread_specific_ptr< thread_data > m_thread_data;

#if defined(BOOST_LOG_USE_COMPILER_TLS)
    //! Cached pointer to the thread-specific data
    static BOOST_LOG_TLS thread_data* m_thread_data_cache;
#endif

#else
    //! Thread-specific data
    std::auto_ptr< thread_data > m_thread_data;
#endif

    //! The global state of logging
    volatile bool m_enabled;
    //! Global filter
    filter m_filter;

    //! Exception handler
    exception_handler_type m_exception_handler;

public:
    //! Constructor
    implementation() :
        m_default_sink(boost::make_shared< sinks::aux::default_sink >()),
        m_enabled(true)
    {
    }

    //! Invokes sink-specific filter and adds the sink to the record if the filter passes the log record
    void apply_sink_filter(shared_ptr< sinks::sink > const& sink, record& rec, attribute_value_set*& attr_values, uint32_t remaining_capacity)
    {
        try
        {<commit_msg>Attempt to workaround ticket #8642.<commit_after>/*
 *          Copyright <NAME> 2007 - 2013.
 * 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   core.cpp
 * \author <NAME>
 * \date   19.04.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 <cstddef>
#include <new>
#include <memory>
#include <vector>
#include <algorithm>
#include <boost/cstdint.hpp>
#include <boost/assert.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/smart_ptr/weak_ptr.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <boost/move/core.hpp>
#include <boost/move/utility.hpp>
#include <boost/log/core/core.hpp>
#include <boost/log/core/record.hpp>
#include <boost/log/core/record_view.hpp>
#include <boost/log/sinks/sink.hpp>
#include <boost/log/attributes/attribute_value_set.hpp>
#include <boost/log/detail/singleton.hpp>
#if !defined(BOOST_LOG_NO_THREADS)
#include <boost/thread/tss.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/log/detail/locks.hpp>
#include <boost/log/detail/light_rw_mutex.hpp>
#endif
#include "default_sink.hpp"
#include "stateless_allocator.hpp"
#include "alignment_gap_between.hpp"
#include <boost/log/detail/header.hpp>

namespace boost {

BOOST_LOG_OPEN_NAMESPACE

//! Private record data information, with core-specific structures
struct record_view::private_data :
    public public_data
{
    //! Underlying memory allocator
    typedef boost::log::aux::stateless_allocator< char > stateless_allocator;
    //! Sink pointer type
    typedef weak_ptr< sinks::sink > sink_ptr;
    //! Iterator range with pointers to the accepting sinks
    typedef iterator_range< sink_ptr* > sink_list;

private:
    //! Number of sinks accepting the record
    uint32_t m_accepting_sink_count;
    //! Maximum number of sinks accepting the record
    const uint32_t m_accepting_sink_capacity;
    //! The flag indicates that the record has to be detached from the current thread
    bool m_detach_from_thread_needed;

private:
    //! Initializing constructor
    private_data(BOOST_RV_REF(attribute_value_set) values, uint32_t capacity) :
        public_data(boost::move(values)),
        m_accepting_sink_count(0),
        m_accepting_sink_capacity(capacity),
        m_detach_from_thread_needed(false)
    {
    }

public:
    //! Creates the object with the specified capacity
    static private_data* create(BOOST_RV_REF(attribute_value_set) values, uint32_t capacity)
    {
        private_data* p = reinterpret_cast< private_data* >(stateless_allocator().allocate
        (
            sizeof(private_data) +
            boost::log::aux::alignment_gap_between< private_data, sink_ptr >::value +
            capacity * sizeof(sink_ptr)
        ));
        new (p) private_data(boost::move(values), capacity);
        return p;
    }

    //! Destroys the object and frees the underlying storage
    void destroy() BOOST_NOEXCEPT
    {
        sink_list s = get_accepting_sinks();
        for (sink_list::iterator it = s.begin(), end = s.end(); it != end; ++it)
        {
            it->~sink_ptr();
        }

        const uint32_t capacity = m_accepting_sink_capacity;
        this->~private_data();

        stateless_allocator().deallocate
        (
            reinterpret_cast< stateless_allocator::pointer >(this),
            sizeof(private_data) +
                boost::log::aux::alignment_gap_between< private_data, sink_ptr >::value +
                capacity * sizeof(sink_ptr)
        );
    }

    //! Returns iterator range with the pointers to the accepting sinks
    sink_list get_accepting_sinks() BOOST_NOEXCEPT
    {
        sink_ptr* p = begin();
        return sink_list(p, p + m_accepting_sink_count);
    }

    //! Adds an accepting sink
    void push_back_accepting_sink(shared_ptr< sinks::sink > const& sink)
    {
        BOOST_ASSERT(m_accepting_sink_count < m_accepting_sink_capacity);
        sink_ptr* p = begin() + m_accepting_sink_count;
        new (p) sink_ptr(sink);
        ++m_accepting_sink_count;
        m_detach_from_thread_needed |= sink->is_cross_thread();
    }

    //! Returns the number of accepting sinks
    uint32_t accepting_sink_count() const BOOST_NOEXCEPT { return m_accepting_sink_count; }

    //! Returns the flag indicating whether it is needed to detach the record from the current thread
    bool is_detach_from_thread_needed() const BOOST_NOEXCEPT { return m_detach_from_thread_needed; }

    BOOST_DELETED_FUNCTION(private_data(private_data const&))
    BOOST_DELETED_FUNCTION(private_data& operator= (private_data const&))

private:
    //! Returns a pointer to the first accepting sink
    sink_ptr* begin() BOOST_NOEXCEPT
    {
        return reinterpret_cast< sink_ptr* >
        (
            reinterpret_cast< char* >(this) +
                sizeof(private_data) +
                boost::log::aux::alignment_gap_between< private_data, sink_ptr >::value
        );
    }
};

//! Destructor
BOOST_LOG_API void record_view::public_data::destroy(const public_data* p) BOOST_NOEXCEPT
{
    const_cast< private_data* >(static_cast< const private_data* >(p))->destroy();
}

//! The function ensures that the log record does not depend on any thread-specific data.
BOOST_LOG_API record_view record::lock()
{
    BOOST_ASSERT(m_impl != NULL);

    record_view::private_data* const impl = static_cast< record_view::private_data* >(m_impl);
    if (impl->is_detach_from_thread_needed())
    {
        attribute_value_set::const_iterator
            it = impl->m_attribute_values.begin(),
            end = impl->m_attribute_values.end();
        for (; it != end; ++it)
        {
            // Yep, a bit hackish. I'll need a better backdoor to do it gracefully.
            const_cast< attribute_value_set::mapped_type& >(it->second).detach_from_thread();
        }
    }

    // Move the implementation to the view
    m_impl = NULL;
    return record_view(impl);
}

//! Logging system implementation
struct core::implementation :
    public log::aux::lazy_singleton<
        implementation,
        core_ptr
    >
{
public:
    //! Base type of singleton holder
    typedef log::aux::lazy_singleton<
        implementation,
        core_ptr
    > base_type;

#if !defined(BOOST_LOG_NO_THREADS)
    //! Read lock type
    typedef log::aux::shared_lock_guard< log::aux::light_rw_mutex > scoped_read_lock;
    //! Write lock type
    typedef log::aux::exclusive_lock_guard< log::aux::light_rw_mutex > scoped_write_lock;
#endif

    //! Sinks container type
    typedef std::vector< shared_ptr< sinks::sink > > sink_list;

    //! Thread-specific data
    struct thread_data
    {
        //! Thread-specific attribute set
        attribute_set m_thread_attributes;
    };

public:
#if !defined(BOOST_LOG_NO_THREADS)
    //! Synchronization mutex
    log::aux::light_rw_mutex m_mutex;
#endif

    //! List of sinks involved into output
    sink_list m_sinks;
    //! Default sink
    const shared_ptr< sinks::sink > m_default_sink;

    //! Global attribute set
    attribute_set m_global_attributes;
#if !defined(BOOST_LOG_NO_THREADS)
    //! Thread-specific data
    thread_specific_ptr< thread_data > m_thread_data;

#if defined(BOOST_LOG_USE_COMPILER_TLS)
    //! Cached pointer to the thread-specific data
    static BOOST_LOG_TLS thread_data* m_thread_data_cache;
#endif

#else
    //! Thread-specific data
    std::auto_ptr< thread_data > m_thread_data;
#endif

    //! The global state of logging
    volatile bool m_enabled;
    //! Global filter
    filter m_filter;

    //! Exception handler
    exception_handler_type m_exception_handler;

public:
    //! Constructor
    implementation() :
        m_default_sink(boost::make_shared< sinks::aux::default_sink >()),
        m_enabled(true)
    {
        // Workaround for https://svn.boost.org/trac/boost/ticket/8642
        // Initialize global locale in Boost.Filesystem early, so that it is still available while the logging core is destroyed.
        // Note that this only helps in the simplest case, when the core is not kept alive by a shared_ptr saved by user.
        filesystem::path::codecvt();
    }

    //! Invokes sink-specific filter and adds the sink to the record if the filter passes the log record
    void apply_sink_filter(shared_ptr< sinks::sink > const& sink, record& rec, attribute_value_set*& attr_values, uint32_t remaining_capacity)
    {
        try
        {
{'fraction_non_alphanumeric': 0.10319280296348562, 'fraction_numerical': 0.004821544070088787, 'mean_word_length': 3.293865185559202, 'pattern_counts': {'":': 0, '<': 110, '<?xml version=': 0, '>': 124, 'https://': 1, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6761123', 'n_tokens_mistral': 5472, 'n_tokens_neox': 5239, 'n_words': 1238}