2
* Copyright Andrey Semashev 2007 - 2013.
3
* Distributed under the Boost Software License, Version 1.0.
4
* (See accompanying file LICENSE_1_0.txt or copy at
5
* http://www.boost.org/LICENSE_1_0.txt)
9
* \author Andrey Semashev
12
* \brief The header defines classes and macros for once-blocks.
15
#ifndef BOOST_LOG_UTILITY_ONCE_BLOCK_HPP_INCLUDED_
16
#define BOOST_LOG_UTILITY_ONCE_BLOCK_HPP_INCLUDED_
18
#include <boost/log/detail/config.hpp>
19
#include <boost/log/utility/unique_identifier_name.hpp>
20
#include <boost/log/detail/header.hpp>
22
#ifdef BOOST_LOG_HAS_PRAGMA_ONCE
26
#ifndef BOOST_LOG_NO_THREADS
30
BOOST_LOG_OPEN_NAMESPACE
33
* \brief A flag to detect if a code block has already been executed.
35
* This structure should be used in conjunction with the \c BOOST_LOG_ONCE_BLOCK_FLAG
36
* macro. Usage example:
41
* static once_block_flag flag = BOOST_LOG_ONCE_BLOCK_INIT;
42
* BOOST_LOG_ONCE_BLOCK_FLAG(flag)
44
* puts("Hello, world once!");
49
struct once_block_flag
51
#ifndef BOOST_LOG_DOXYGEN_PASS
52
// Do not use, implementation detail
60
#endif // BOOST_LOG_DOXYGEN_PASS
64
* \def BOOST_LOG_ONCE_BLOCK_INIT
66
* The static initializer for \c once_block_flag.
68
#define BOOST_LOG_ONCE_BLOCK_INIT { boost::log::once_block_flag::uninitialized }
72
class once_block_sentry
75
once_block_flag& m_Flag;
78
explicit once_block_sentry(once_block_flag& f) : m_Flag(f)
84
if (m_Flag.status != once_block_flag::initialized)
90
return (m_Flag.status == once_block_flag::initialized || enter_once_block());
93
BOOST_LOG_API void commit();
96
// Non-copyable, non-assignable
97
once_block_sentry(once_block_sentry const&);
98
once_block_sentry& operator= (once_block_sentry const&);
100
BOOST_LOG_API bool enter_once_block() const;
101
BOOST_LOG_API void rollback();
106
BOOST_LOG_CLOSE_NAMESPACE // namespace log
110
#else // BOOST_LOG_NO_THREADS
114
BOOST_LOG_OPEN_NAMESPACE
116
struct once_block_flag
121
#define BOOST_LOG_ONCE_BLOCK_INIT { false }
125
class once_block_sentry
128
once_block_flag& m_Flag;
131
explicit once_block_sentry(once_block_flag& f) : m_Flag(f)
135
bool executed() const
137
return m_Flag.status;
142
m_Flag.status = true;
146
// Non-copyable, non-assignable
147
once_block_sentry(once_block_sentry const&);
148
once_block_sentry& operator= (once_block_sentry const&);
153
BOOST_LOG_CLOSE_NAMESPACE // namespace log
157
#endif // BOOST_LOG_NO_THREADS
159
#ifndef BOOST_LOG_DOXYGEN_PASS
161
#define BOOST_LOG_ONCE_BLOCK_FLAG_INTERNAL(flag_var, sentry_var)\
162
for (boost::log::aux::once_block_sentry sentry_var((flag_var));\
163
!sentry_var.executed(); sentry_var.commit())
165
#define BOOST_LOG_ONCE_BLOCK_INTERNAL(flag_var, sentry_var)\
166
static boost::log::once_block_flag flag_var = BOOST_LOG_ONCE_BLOCK_INIT;\
167
BOOST_LOG_ONCE_BLOCK_FLAG_INTERNAL(flag_var, sentry_var)
169
#endif // BOOST_LOG_DOXYGEN_PASS
172
* \def BOOST_LOG_ONCE_BLOCK_FLAG(flag_var)
174
* Begins a code block to be executed only once, with protection against thread concurrency.
175
* User has to provide the flag variable that controls whether the block has already
178
#define BOOST_LOG_ONCE_BLOCK_FLAG(flag_var)\
179
BOOST_LOG_ONCE_BLOCK_INTERNAL(\
181
BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_once_block_sentry_))
184
* \def BOOST_LOG_ONCE_BLOCK()
186
* Begins a code block to be executed only once, with protection against thread concurrency.
188
#define BOOST_LOG_ONCE_BLOCK()\
189
BOOST_LOG_ONCE_BLOCK_INTERNAL(\
190
BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_once_block_flag_),\
191
BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_once_block_sentry_))
193
#include <boost/log/detail/footer.hpp>
195
#endif // BOOST_LOG_UTILITY_ONCE_BLOCK_HPP_INCLUDED_