Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:29

0001 /*
0002  *          Copyright Andrey Semashev 2007 - 2015.
0003  * Distributed under the Boost Software License, Version 1.0.
0004  *    (See accompanying file LICENSE_1_0.txt or copy at
0005  *          http://www.boost.org/LICENSE_1_0.txt)
0006  */
0007 /*!
0008  * \file   once_block.hpp
0009  * \author Andrey Semashev
0010  * \date   23.06.2010
0011  *
0012  * \brief  The header defines classes and macros for once-blocks.
0013  */
0014 
0015 #ifndef BOOST_LOG_UTILITY_ONCE_BLOCK_HPP_INCLUDED_
0016 #define BOOST_LOG_UTILITY_ONCE_BLOCK_HPP_INCLUDED_
0017 
0018 #include <boost/log/detail/config.hpp>
0019 #include <boost/log/utility/unique_identifier_name.hpp>
0020 #include <boost/log/detail/header.hpp>
0021 
0022 #ifdef BOOST_HAS_PRAGMA_ONCE
0023 #pragma once
0024 #endif
0025 
0026 #ifndef BOOST_LOG_NO_THREADS
0027 
0028 namespace boost {
0029 
0030 BOOST_LOG_OPEN_NAMESPACE
0031 
0032 /*!
0033  * \brief A flag to detect if a code block has already been executed.
0034  *
0035  * This structure should be used in conjunction with the \c BOOST_LOG_ONCE_BLOCK_FLAG
0036  * macro. Usage example:
0037  *
0038  * <code>
0039  * once_block_flag flag = BOOST_LOG_ONCE_BLOCK_INIT;
0040  *
0041  * void foo()
0042  * {
0043  *     BOOST_LOG_ONCE_BLOCK_FLAG(flag)
0044  *     {
0045  *         puts("Hello, world once!");
0046  *     }
0047  * }
0048  * </code>
0049  */
0050 struct once_block_flag
0051 {
0052 #ifndef BOOST_LOG_DOXYGEN_PASS
0053     // Do not use, implementation detail
0054     enum
0055     {
0056         uninitialized = 0, // this must be zero, so that zero-initialized once_block_flag is equivalent to the one initialized with uninitialized
0057         being_initialized,
0058         initialized
0059     };
0060     unsigned char status;
0061 #endif // BOOST_LOG_DOXYGEN_PASS
0062 };
0063 
0064 /*!
0065  * \def BOOST_LOG_ONCE_BLOCK_INIT
0066  *
0067  * The static initializer for \c once_block_flag.
0068  */
0069 #define BOOST_LOG_ONCE_BLOCK_INIT { boost::log::once_block_flag::uninitialized }
0070 
0071 namespace aux {
0072 
0073 class once_block_sentry
0074 {
0075 private:
0076     once_block_flag& m_flag;
0077 
0078 public:
0079     explicit once_block_sentry(once_block_flag& f) BOOST_NOEXCEPT : m_flag(f)
0080     {
0081     }
0082 
0083     ~once_block_sentry() BOOST_NOEXCEPT
0084     {
0085         if (BOOST_UNLIKELY(m_flag.status != once_block_flag::initialized))
0086             rollback();
0087     }
0088 
0089     bool executed() const BOOST_NOEXCEPT
0090     {
0091         return (m_flag.status == once_block_flag::initialized || enter_once_block());
0092     }
0093 
0094     BOOST_LOG_API void commit() BOOST_NOEXCEPT;
0095 
0096 private:
0097     BOOST_LOG_API bool enter_once_block() const BOOST_NOEXCEPT;
0098     BOOST_LOG_API void rollback() BOOST_NOEXCEPT;
0099 
0100     //  Non-copyable, non-assignable
0101     BOOST_DELETED_FUNCTION(once_block_sentry(once_block_sentry const&))
0102     BOOST_DELETED_FUNCTION(once_block_sentry& operator= (once_block_sentry const&))
0103 };
0104 
0105 } // namespace aux
0106 
0107 BOOST_LOG_CLOSE_NAMESPACE // namespace log
0108 
0109 } // namespace boost
0110 
0111 #else // BOOST_LOG_NO_THREADS
0112 
0113 namespace boost {
0114 
0115 BOOST_LOG_OPEN_NAMESPACE
0116 
0117 struct once_block_flag
0118 {
0119     bool status;
0120 };
0121 
0122 #define BOOST_LOG_ONCE_BLOCK_INIT { false }
0123 
0124 namespace aux {
0125 
0126 class once_block_sentry
0127 {
0128 private:
0129     once_block_flag& m_flag;
0130 
0131 public:
0132     explicit once_block_sentry(once_block_flag& f) BOOST_NOEXCEPT : m_flag(f)
0133     {
0134     }
0135 
0136     bool executed() const BOOST_NOEXCEPT
0137     {
0138         return m_flag.status;
0139     }
0140 
0141     void commit() BOOST_NOEXCEPT
0142     {
0143         m_flag.status = true;
0144     }
0145 
0146     //  Non-copyable, non-assignable
0147     BOOST_DELETED_FUNCTION(once_block_sentry(once_block_sentry const&))
0148     BOOST_DELETED_FUNCTION(once_block_sentry& operator= (once_block_sentry const&))
0149 };
0150 
0151 } // namespace aux
0152 
0153 BOOST_LOG_CLOSE_NAMESPACE // namespace log
0154 
0155 } // namespace boost
0156 
0157 #endif // BOOST_LOG_NO_THREADS
0158 
0159 #ifndef BOOST_LOG_DOXYGEN_PASS
0160 
0161 #define BOOST_LOG_ONCE_BLOCK_FLAG_INTERNAL(flag_var, sentry_var)\
0162     for (boost::log::aux::once_block_sentry sentry_var((flag_var));\
0163         BOOST_UNLIKELY(!sentry_var.executed()); sentry_var.commit())
0164 
0165 // NOTE: flag_var deliberately doesn't have an initializer so that it is zero-initialized at the static initialization stage
0166 #define BOOST_LOG_ONCE_BLOCK_INTERNAL(flag_var, sentry_var)\
0167     static boost::log::once_block_flag flag_var;\
0168     BOOST_LOG_ONCE_BLOCK_FLAG_INTERNAL(flag_var, sentry_var)
0169 
0170 #endif // BOOST_LOG_DOXYGEN_PASS
0171 
0172 /*!
0173  * \def BOOST_LOG_ONCE_BLOCK_FLAG(flag_var)
0174  *
0175  * Begins a code block to be executed only once, with protection against thread concurrency.
0176  * User has to provide the flag variable that controls whether the block has already
0177  * been executed.
0178  */
0179 #define BOOST_LOG_ONCE_BLOCK_FLAG(flag_var)\
0180     BOOST_LOG_ONCE_BLOCK_FLAG_INTERNAL(\
0181         flag_var,\
0182         BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_once_block_sentry_))
0183 
0184 /*!
0185  * \def BOOST_LOG_ONCE_BLOCK()
0186  *
0187  * Begins a code block to be executed only once, with protection against thread concurrency.
0188  */
0189 #define BOOST_LOG_ONCE_BLOCK()\
0190     BOOST_LOG_ONCE_BLOCK_INTERNAL(\
0191         BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_once_block_flag_),\
0192         BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_once_block_sentry_))
0193 
0194 #include <boost/log/detail/footer.hpp>
0195 
0196 #endif // BOOST_LOG_UTILITY_ONCE_BLOCK_HPP_INCLUDED_