Fixed data race in flat combining algo found by TSan
authorkhizmax <libcds.dev@gmail.com>
Fri, 12 Jun 2015 21:05:45 +0000 (00:05 +0300)
committerkhizmax <libcds.dev@gmail.com>
Fri, 12 Jun 2015 21:05:45 +0000 (00:05 +0300)
cds/algo/flat_combining.h

index b239ef4218c61d2d48cab914c968a2cbc3094c4f..0f382d404a6a2e5cb04c9fd151ff9318d4e78d21 100644 (file)
@@ -262,7 +262,7 @@ namespace cds { namespace algo {
             //@endcond
 
         protected:
-            unsigned int                m_nCount;   ///< Count of combining passes
+            atomics::atomic<unsigned int>  m_nCount;   ///< Total count of combining passes. Used as an age.
             publication_record_type *   m_pHead;    ///< Head of publication list
             boost::thread_specific_ptr< publication_record_type >   m_pThreadRec;   ///< Thread-local publication record
             mutable global_lock_type    m_Mutex;    ///< Global mutex
@@ -565,7 +565,7 @@ namespace cds { namespace algo {
             {
                 assert( pRec->nState.load( memory_model::memory_order_relaxed ) == inactive );
 
-                pRec->nAge.store( m_nCount, memory_model::memory_order_release );
+                pRec->nAge.store( m_nCount.load(memory_model::memory_order_acquire), memory_model::memory_order_release );
                 pRec->nState.store( active, memory_model::memory_order_release );
 
                 // Insert record to publication list
@@ -652,7 +652,7 @@ namespace cds { namespace algo {
                 // The thread is a combiner
                 assert( !m_Mutex.try_lock() );
 
-                unsigned int const nCurAge = ++m_nCount;
+                unsigned int const nCurAge = m_nCount.fetch_add( 1, memory_model::memory_order_release ) + 1;
 
                 for ( unsigned int nPass = 0; nPass < m_nCombinePassCount; ++nPass )
                     if ( !combining_pass( owner, nCurAge ))
@@ -703,7 +703,7 @@ namespace cds { namespace algo {
                 // The thread is a combiner
                 assert( !m_Mutex.try_lock() );
 
-                unsigned int const nCurAge = ++m_nCount;
+                unsigned int const nCurAge = m_nCount.fetch_add( 1, memory_model::memory_order_release ) + 1;
 
                 for ( unsigned int nPass = 0; nPass < m_nCombinePassCount; ++nPass )
                     owner.fc_process( begin(), end() );