Fixed missing acquire read in Flat-Combining algorithm (found by TSan)
[libcds.git] / cds / algo / flat_combining / kernel.h
index 5e333e157bf4daeb1205285e2f715c3af4db126d..202293b4f19a14f270be6abfa5388ec8d776e480 100644 (file)
@@ -324,9 +324,9 @@ namespace cds { namespace algo {
 
                     // Insert in allocated list
                     assert( m_pAllocatedHead != nullptr );
-                    publication_record* p = m_pAllocatedHead->pNextAllocated.load( memory_model::memory_order_acquire );
+                    publication_record* p = m_pAllocatedHead->pNextAllocated.load( memory_model::memory_order_relaxed );
                     do {
-                        pRec->pNextAllocated.store( p, memory_model::memory_order_relaxed );
+                        pRec->pNextAllocated.store( p, memory_model::memory_order_release );
                     } while ( !m_pAllocatedHead->pNextAllocated.compare_exchange_weak( p, pRec, memory_model::memory_order_release, atomics::memory_order_acquire ));
 
                     publish( pRec );
@@ -422,7 +422,7 @@ namespace cds { namespace algo {
 
             /// Marks \p rec as executed
             /**
-                This function should be called by container if \p batch_combine mode is used.
+                This function should be called by container if \p batch_combine() mode is used.
                 For usual combining (see \p combine()) this function is excess.
             */
             void operation_done( publication_record& rec )
@@ -602,10 +602,10 @@ namespace cds { namespace algo {
 
                 // Insert record to publication list
                 if ( m_pHead != static_cast<publication_record *>(pRec)) {
-                    publication_record * p = m_pHead->pNext.load(memory_model::memory_order_relaxed);
+                    publication_record * p = m_pHead->pNext.load( memory_model::memory_order_relaxed );
                     if ( p != static_cast<publication_record *>( pRec )) {
                         do {
-                            pRec->pNext.store( p, memory_model::memory_order_relaxed );
+                            pRec->pNext.store( p, memory_model::memory_order_release );
                             // Failed CAS changes p
                         } while ( !m_pHead->pNext.compare_exchange_weak( p, static_cast<publication_record *>(pRec),
                             memory_model::memory_order_release, atomics::memory_order_acquire ));
@@ -708,7 +708,7 @@ namespace cds { namespace algo {
                 while ( p ) {
                     switch ( p->nState.load( memory_model::memory_order_acquire )) {
                     case active:
-                        if ( p->op() >= req_Operation ) {
+                        if ( p->op( memory_model::memory_order_acquire ) >= req_Operation ) {
                             p->nAge.store( nCurAge, memory_model::memory_order_relaxed );
                             owner.fc_apply( static_cast<publication_record_type*>( p ));
                             operation_done( *p );
@@ -748,7 +748,7 @@ namespace cds { namespace algo {
                     compact_list( nCurAge );
             }
 
-            bool wait_for_combining( publication_record_type * pRec )
+            bool wait_for_combining( publication_record_type* pRec )
             {
                 m_waitStrategy.prepare( *pRec );
                 m_Stat.onPassiveWait();
@@ -864,4 +864,37 @@ namespace cds { namespace algo {
     } // namespace flat_combining
 }} // namespace cds::algo
 
+/*
+  CppMem model  (http://svr-pes20-cppmem.cl.cam.ac.uk/cppmem/)
+
+  // Combiner thread - slave (waiting) thread
+int main() {
+      atomic_int y = 0;  // pRec->op
+      int x = 0;         // pRec->data
+   {{{
+      { // slave thread (not combiner)
+        // Op data
+        x = 1;
+        // Annotate request (op)
+        y.store(1, release);
+        // Wait while request done
+        y.load(acquire).readsvalue(2);
+        // Read result
+        r2=x;
+      }
+   |||
+      { // Combiner thread
+        // Read request (op)
+        r1=y.load(acquire).readsvalue(1);
+        // Execute request - change request data
+        x = 2;
+        // store "request processed" flag (pRec->op := req_Response)
+        y.store(2, release);
+      }
+   }}};
+   return 0;
+}
+
+*/
+
 #endif // #ifndef CDSLIB_ALGO_FLAT_COMBINING_KERNEL_H