Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r84918 - in trunk: boost/log/utility libs/log/src libs/log/test/run
From: andrey.semashev_at_[hidden]
Date: 2013-06-30 09:29:25


Author: andysem
Date: 2013-06-30 09:29:25 EDT (Sun, 30 Jun 2013)
New Revision: 84918
URL: http://svn.boost.org/trac/boost/changeset/84918

Log:
Refs #8730. The once_flag doesn't have initializer now when defined by the BOOST_LOG_ONCE_BLOCK macro. This is done in order to guarantee it is initialized at static initialization stage even on (theoretical) compilers that would not do so if the initializer is present. The BOOST_LOG_ONCE_BLOCK_FLAG macro has been fixed so that it actually uses the flag variable specified in its argument. The flag itself is now a single byte internally in order to minimize the chance of reading an inaccurate value at the fast path. The test robustness improved.

Text files modified:
   trunk/boost/log/utility/once_block.hpp | 30 ++++++++++++++++--------------
   trunk/libs/log/src/once_block.cpp | 18 +++++++++---------
   trunk/libs/log/test/run/util_once_block.cpp | 21 +++++++++++++++------
   3 files changed, 40 insertions(+), 29 deletions(-)

Modified: trunk/boost/log/utility/once_block.hpp
==============================================================================
--- trunk/boost/log/utility/once_block.hpp Sun Jun 30 07:05:21 2013 (r84917)
+++ trunk/boost/log/utility/once_block.hpp 2013-06-30 09:29:25 EDT (Sun, 30 Jun 2013) (r84918)
@@ -36,9 +36,10 @@
  * macro. Usage example:
  *
  * <code>
+ * once_block_flag flag = BOOST_LOG_ONCE_BLOCK_INIT;
+ *
  * void foo()
  * {
- * static once_block_flag flag = BOOST_LOG_ONCE_BLOCK_INIT;
  * BOOST_LOG_ONCE_BLOCK_FLAG(flag)
  * {
  * puts("Hello, world once!");
@@ -52,11 +53,11 @@
     // Do not use, implementation detail
     enum
     {
- uninitialized = 0,
+ uninitialized = 0, // this must be zero, so that zero-initialized once_block_flag is equivalent to the one initialized with uninitialized
         being_initialized,
         initialized
- }
- status;
+ };
+ unsigned char status;
 #endif // BOOST_LOG_DOXYGEN_PASS
 };
 
@@ -72,22 +73,22 @@
 class once_block_sentry
 {
 private:
- once_block_flag& m_Flag;
+ once_block_flag& m_flag;
 
 public:
- explicit once_block_sentry(once_block_flag& f) : m_Flag(f)
+ explicit once_block_sentry(once_block_flag& f) : m_flag(f)
     {
     }
 
     ~once_block_sentry()
     {
- if (m_Flag.status != once_block_flag::initialized)
+ if (m_flag.status != once_block_flag::initialized)
             rollback();
     }
 
     bool executed() const
     {
- return (m_Flag.status == once_block_flag::initialized || enter_once_block());
+ return (m_flag.status == once_block_flag::initialized || enter_once_block());
     }
 
     BOOST_LOG_API void commit();
@@ -125,21 +126,21 @@
 class once_block_sentry
 {
 private:
- once_block_flag& m_Flag;
+ once_block_flag& m_flag;
 
 public:
- explicit once_block_sentry(once_block_flag& f) : m_Flag(f)
+ explicit once_block_sentry(once_block_flag& f) : m_flag(f)
     {
     }
 
     bool executed() const
     {
- return m_Flag.status;
+ return m_flag.status;
     }
 
     void commit()
     {
- m_Flag.status = true;
+ m_flag.status = true;
     }
 
 private:
@@ -162,8 +163,9 @@
     for (boost::log::aux::once_block_sentry sentry_var((flag_var));\
         !sentry_var.executed(); sentry_var.commit())
 
+// NOTE: flag_var deliberately doesn't have an initializer so that it is zero-initialized at the static initialization stage
 #define BOOST_LOG_ONCE_BLOCK_INTERNAL(flag_var, sentry_var)\
- static boost::log::once_block_flag flag_var = BOOST_LOG_ONCE_BLOCK_INIT;\
+ static boost::log::once_block_flag flag_var;\
     BOOST_LOG_ONCE_BLOCK_FLAG_INTERNAL(flag_var, sentry_var)
 
 #endif // BOOST_LOG_DOXYGEN_PASS
@@ -176,7 +178,7 @@
  * been executed.
  */
 #define BOOST_LOG_ONCE_BLOCK_FLAG(flag_var)\
- BOOST_LOG_ONCE_BLOCK_INTERNAL(\
+ BOOST_LOG_ONCE_BLOCK_FLAG_INTERNAL(\
         flag_var,\
         BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_once_block_sentry_))
 

Modified: trunk/libs/log/src/once_block.cpp
==============================================================================
--- trunk/libs/log/src/once_block.cpp Sun Jun 30 07:05:21 2013 (r84917)
+++ trunk/libs/log/src/once_block.cpp 2013-06-30 09:29:25 EDT (Sun, 30 Jun 2013) (r84918)
@@ -46,7 +46,7 @@
 {
     AcquireSRWLockExclusive(&g_OnceBlockMutex);
 
- once_block_flag volatile& flag = m_Flag;
+ once_block_flag volatile& flag = m_flag;
     while (flag.status != once_block_flag::initialized)
     {
         if (flag.status == once_block_flag::uninitialized)
@@ -77,7 +77,7 @@
     AcquireSRWLockExclusive(&g_OnceBlockMutex);
 
     // The initializer executed successfully
- m_Flag.status = once_block_flag::initialized;
+ m_flag.status = once_block_flag::initialized;
 
     ReleaseSRWLockExclusive(&g_OnceBlockMutex);
     WakeAllConditionVariable(&g_OnceBlockCond);
@@ -88,7 +88,7 @@
     AcquireSRWLockExclusive(&g_OnceBlockMutex);
 
     // The initializer failed, marking the flag as if it hasn't run at all
- m_Flag.status = once_block_flag::uninitialized;
+ m_flag.status = once_block_flag::uninitialized;
 
     ReleaseSRWLockExclusive(&g_OnceBlockMutex);
     WakeAllConditionVariable(&g_OnceBlockCond);
@@ -354,17 +354,17 @@
 
 BOOST_LOG_API bool once_block_sentry::enter_once_block() const
 {
- return get_once_block_impl()->enter_once_block(m_Flag);
+ return get_once_block_impl()->enter_once_block(m_flag);
 }
 
 BOOST_LOG_API void once_block_sentry::commit()
 {
- get_once_block_impl()->commit(m_Flag);
+ get_once_block_impl()->commit(m_flag);
 }
 
 BOOST_LOG_API void once_block_sentry::rollback()
 {
- get_once_block_impl()->rollback(m_Flag);
+ get_once_block_impl()->rollback(m_flag);
 }
 
 } // namespace aux
@@ -399,7 +399,7 @@
 {
     BOOST_VERIFY(!pthread_mutex_lock(&g_OnceBlockMutex));
 
- once_block_flag volatile& flag = m_Flag;
+ once_block_flag volatile& flag = m_flag;
     while (flag.status != once_block_flag::initialized)
     {
         if (flag.status == once_block_flag::uninitialized)
@@ -429,7 +429,7 @@
     BOOST_VERIFY(!pthread_mutex_lock(&g_OnceBlockMutex));
 
     // The initializer executed successfully
- m_Flag.status = once_block_flag::initialized;
+ m_flag.status = once_block_flag::initialized;
 
     BOOST_VERIFY(!pthread_mutex_unlock(&g_OnceBlockMutex));
     BOOST_VERIFY(!pthread_cond_broadcast(&g_OnceBlockCond));
@@ -440,7 +440,7 @@
     BOOST_VERIFY(!pthread_mutex_lock(&g_OnceBlockMutex));
 
     // The initializer failed, marking the flag as if it hasn't run at all
- m_Flag.status = once_block_flag::uninitialized;
+ m_flag.status = once_block_flag::uninitialized;
 
     BOOST_VERIFY(!pthread_mutex_unlock(&g_OnceBlockMutex));
     BOOST_VERIFY(!pthread_cond_broadcast(&g_OnceBlockCond));

Modified: trunk/libs/log/test/run/util_once_block.cpp
==============================================================================
--- trunk/libs/log/test/run/util_once_block.cpp Sun Jun 30 07:05:21 2013 (r84917)
+++ trunk/libs/log/test/run/util_once_block.cpp 2013-06-30 09:29:25 EDT (Sun, 30 Jun 2013) (r84918)
@@ -21,9 +21,12 @@
 
 #if !defined(BOOST_LOG_NO_THREADS)
 
+#include <boost/ref.hpp>
+#include <boost/bind.hpp>
 #include <boost/thread/thread.hpp>
 #include <boost/thread/mutex.hpp>
 #include <boost/thread/locks.hpp>
+#include <boost/thread/barrier.hpp>
 
 namespace logging = boost::log;
 
@@ -47,9 +50,10 @@
 }
 
 
-void once_block_flag_thread()
+void once_block_flag_thread(boost::barrier& barrier)
 {
     int my_once_value = 0;
+ barrier.wait();
     for (unsigned int i = 0; i < LOOP_COUNT; ++i)
     {
         BOOST_LOG_ONCE_BLOCK_FLAG(flag)
@@ -71,12 +75,13 @@
 BOOST_AUTO_TEST_CASE(once_block_flag)
 {
     boost::thread_group group;
+ boost::barrier barrier(static_cast< unsigned int >(THREAD_COUNT));
 
     try
     {
         for (unsigned int i = 0; i < THREAD_COUNT; ++i)
         {
- group.create_thread(&once_block_flag_thread);
+ group.create_thread(boost::bind(&once_block_flag_thread, boost::ref(barrier)));
         }
         group.join_all();
     }
@@ -92,9 +97,10 @@
 
 int var_to_init_once = 0;
 
-void once_block_thread()
+void once_block_thread(boost::barrier& barrier)
 {
     int my_once_value = 0;
+ barrier.wait();
     for (unsigned int i = 0; i < LOOP_COUNT; ++i)
     {
         BOOST_LOG_ONCE_BLOCK()
@@ -118,12 +124,13 @@
 BOOST_AUTO_TEST_CASE(once_block)
 {
     boost::thread_group group;
+ boost::barrier barrier(static_cast< unsigned int >(THREAD_COUNT));
 
     try
     {
         for (unsigned int i = 0; i < THREAD_COUNT; ++i)
         {
- group.create_thread(&once_block_thread);
+ group.create_thread(boost::bind(&once_block_thread, boost::ref(barrier)));
         }
         group.join_all();
     }
@@ -145,8 +152,9 @@
 unsigned int pass_counter = 0;
 unsigned int exception_counter = 0;
 
-void once_block_with_exception_thread()
+void once_block_with_exception_thread(boost::barrier& barrier)
 {
+ barrier.wait();
     try
     {
         BOOST_LOG_ONCE_BLOCK()
@@ -170,12 +178,13 @@
 BOOST_AUTO_TEST_CASE(once_block_retried_on_exception)
 {
     boost::thread_group group;
+ boost::barrier barrier(static_cast< unsigned int >(THREAD_COUNT));
 
     try
     {
         for (unsigned int i = 0; i < THREAD_COUNT; ++i)
         {
- group.create_thread(&once_block_with_exception_thread);
+ group.create_thread(boost::bind(&once_block_with_exception_thread, boost::ref(barrier)));
         }
         group.join_all();
     }


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk