Added simplified form of urcu::batch_retire function
authorkhizmax <libcds.dev@gmail.com>
Thu, 21 May 2015 21:47:02 +0000 (00:47 +0300)
committerkhizmax <libcds.dev@gmail.com>
Thu, 21 May 2015 21:47:02 +0000 (00:47 +0300)
Added cds::gc::make_retired_ptr function

14 files changed:
cds/gc/details/retired_ptr.h
cds/intrusive/michael_list_rcu.h
cds/urcu/details/base.h
cds/urcu/details/gp.h
cds/urcu/details/gpb.h
cds/urcu/details/gpi.h
cds/urcu/details/gpt.h
cds/urcu/details/sig_buffered.h
cds/urcu/details/sig_threaded.h
cds/urcu/general_buffered.h
cds/urcu/general_instant.h
cds/urcu/general_threaded.h
cds/urcu/signal_buffered.h
cds/urcu/signal_threaded.h

index bf3d7da81719fb0d16e879bfa47312fc05268ea4..ae359441245bf545fca272d35857a468ca14a9b8 100644 (file)
@@ -4,6 +4,7 @@
 #define CDSLIB_GC_DETAILS_RETIRED_PTR_H
 
 #include <cds/details/defs.h>
+#include <cds/details/static_functor.h>
 
 //@cond
 namespace cds { namespace gc {
@@ -87,6 +88,13 @@ namespace cds { namespace gc {
             return !(p1 == p2);
         }
     }  // namespace details
+
+    template <typename Func, typename T>
+    cds::gc::details::retired_ptr make_retired_ptr( T * p )
+    {
+        return cds::gc::details::retired_ptr( p, cds::details::static_functor<Func, T>::call );
+    }
+
 }}   // namespace cds::gc
 //@endcond
 
index 8a69ae6c5bf2d9056c24168e87383f550a318290..e41d912cdbfbe8e402424b56217f4196dd7ace1d 100644 (file)
@@ -168,13 +168,14 @@ namespace cds { namespace intrusive {
             {
                 assert( !gc::is_locked() );
 
-                node_type * p = pDelChain;
-                if ( p ) {
-                    while ( p ) {
-                        node_type * pNext = p->m_pDelChain;
-                        dispose_node( p );
-                        p = pNext;
-                    }
+                node_type * chain = pDelChain;
+                if ( chain ) {
+                    auto f = [&chain]() -> cds::urcu::retired_ptr {
+                        node_type * p = chain;
+                        chain = p->m_pDelChain;
+                        return cds::urcu::make_retired_ptr<clear_and_dispose>( node_traits::to_value_ptr( p ));
+                    };
+                    gc::batch_retire(std::ref(f));
                 }
             }
         };
@@ -721,7 +722,7 @@ namespace cds { namespace intrusive {
         template <typename Q>
         value_type * get( Q const& key )
         {
-            return get_at( const_cast<atomic_node_ptr&>( m_pHead ), key, key_comparator());
+            return get_at( m_pHead, key, key_comparator());
         }
 
         /// Finds \p key and return the item found
@@ -737,7 +738,7 @@ namespace cds { namespace intrusive {
         value_type * get_with( Q const& key, Less pred )
         {
             CDS_UNUSED( pred );
-            return get_at( const_cast<atomic_node_ptr&>( m_pHead ), key, cds::opt::details::make_comparator_from_less<Less>());
+            return get_at( m_pHead, key, cds::opt::details::make_comparator_from_less<Less>());
         }
 
         /// Clears the list using default disposer
index 76420833334d5f6b20d2403cf200733de4db23a1..8c6e726d33b4af9329e9ccc0cbff5144b1c304b8 100644 (file)
@@ -255,6 +255,7 @@ namespace cds {
 
         ///@anchor cds_urcu_retired_ptr Retired pointer, i.e. pointer that ready for reclamation
         typedef cds::gc::details::retired_ptr   retired_ptr;
+        using cds::gc::make_retired_ptr;
 
         /// Pointer to function to free (destruct and deallocate) retired pointer of specific type
         typedef cds::gc::details::free_retired_ptr_func free_retired_ptr_func;
index cd30b98bbc65462931c9474f0d9419f4079bd7e4..3f6dc83fdafafe2358796a1628532c21529dbb9c 100644 (file)
@@ -42,7 +42,7 @@ namespace cds { namespace urcu { namespace details {
             pRec->m_nAccessControl.store( gp_singleton<RCUtag>::instance()->global_control_word(atomics::memory_order_relaxed),
                 atomics::memory_order_relaxed );
             atomics::atomic_thread_fence( atomics::memory_order_acquire );
-            //CDS_COMPILER_RW_BARRIER;
+            CDS_COMPILER_RW_BARRIER;
         }
         else {
             pRec->m_nAccessControl.fetch_add( 1, atomics::memory_order_relaxed );
@@ -55,7 +55,7 @@ namespace cds { namespace urcu { namespace details {
         thread_record * pRec = get_thread_record();
         assert( pRec != nullptr );
 
-        //CDS_COMPILER_RW_BARRIER;
+        CDS_COMPILER_RW_BARRIER;
         pRec->m_nAccessControl.fetch_sub( 1, atomics::memory_order_release );
     }
 
index 229aded845a53e96e00d643fc5bc8c99a860e255..9441f26b433bd2b3f273dc9ee091720c138eb3cc 100644 (file)
@@ -111,14 +111,14 @@ namespace cds { namespace urcu {
                     p.free();
                 }
                 else {
-                    push_buffer( p );
+                    push_buffer( std::move(p) );
                     break;
                 }
             }
         }
 
         // Return: true - synchronize has been called, false - otherwise
-        bool push_buffer( epoch_retired_ptr& ep )
+        bool push_buffer( epoch_retired_ptr&& ep )
         {
             bool bPushed = m_Buffer.push( ep );
             if ( !bPushed || m_Buffer.size() >= capacity() ) {
@@ -164,10 +164,8 @@ namespace cds { namespace urcu {
         */
         virtual void retire_ptr( retired_ptr& p )
         {
-            if ( p.m_p ) {
-                epoch_retired_ptr ep( p, m_nCurEpoch.load( atomics::memory_order_relaxed ));
-                push_buffer( ep );
-            }
+            if ( p.m_p )
+                push_buffer( epoch_retired_ptr( p, m_nCurEpoch.load( atomics::memory_order_relaxed )));
         }
 
         /// Retires the pointer chain [\p itFirst, \p itLast)
@@ -176,12 +174,20 @@ namespace cds { namespace urcu {
         {
             uint64_t nEpoch = m_nCurEpoch.load( atomics::memory_order_relaxed );
             while ( itFirst != itLast ) {
-                epoch_retired_ptr ep( *itFirst, nEpoch );
+                push_buffer( epoch_retired_ptr( *itFirst, nEpoch ));
                 ++itFirst;
-                push_buffer( ep );
             }
         }
 
+        /// Retires the pointer chain until \p Func returns \p nullptr retired pointer
+        template <typename Func>
+        void batch_retire( Func e )
+        {
+            uint64_t nEpoch = m_nCurEpoch.load( atomics::memory_order_relaxed );
+            for ( retired_ptr p{ e() }; p.m_p; p = e() )
+                push_buffer( epoch_retired_ptr( p, nEpoch ));
+        }
+
         /// Wait to finish a grace period and then clear the buffer
         void synchronize()
         {
index 1e5426ba0be212c90641f8110104b9eb7b210110..776a09fcc870ee57aa17b920d1e3cf5cd1cba329 100644 (file)
@@ -111,11 +111,8 @@ namespace cds { namespace urcu {
         virtual void retire_ptr( retired_ptr& p )
         {
             synchronize();
-            if ( p.m_p ) {
-                // TSan ignores atomic_thread_fence in synchronize()
-                //CDS_TSAN_ANNOTATE_HAPPENS_BEFORE( p.m_p );
+            if ( p.m_p )
                 p.free();
-            }
         }
 
         /// Retires the pointer chain [\p itFirst, \p itLast)
@@ -127,15 +124,24 @@ namespace cds { namespace urcu {
                 while ( itFirst != itLast ) {
                     retired_ptr p( *itFirst );
                     ++itFirst;
-                    if ( p.m_p ) {
-                        // TSan ignores atomic_thread_fence in synchronize()
-                        //CDS_TSAN_ANNOTATE_HAPPENS_BEFORE( p.m_p );
+                    if ( p.m_p )
                         p.free();
-                    }
                 }
             }
         }
 
+        /// Retires the pointer chain until \p Func returns \p nullptr retired pointer
+        template <typename Func>
+        void batch_retire( Func e )
+        {
+            retired_ptr p{ e() };
+            if ( p.m_p ) {
+                synchronize();
+                for ( ; p.m_p; p = e() )
+                    p.free();
+            }
+        }
+
         /// Waits to finish a grace period
         void synchronize()
         {
index 30bb1ebb0eaceff60ec99cac5361b4ad3d1420df..1f5941481f91156ec8a09ba4f54846dce0971482 100644 (file)
@@ -108,7 +108,7 @@ namespace cds { namespace urcu {
         }
 
         // Return: true - synchronize has been called, false - otherwise
-        bool push_buffer( epoch_retired_ptr& p )
+        bool push_buffer( epoch_retired_ptr&& p )
         {
             bool bPushed = m_Buffer.push( p );
             if ( !bPushed || m_Buffer.size() >= capacity() ) {
@@ -168,10 +168,8 @@ namespace cds { namespace urcu {
         */
         virtual void retire_ptr( retired_ptr& p )
         {
-            if ( p.m_p ) {
-                epoch_retired_ptr ep( p, m_nCurEpoch.load( atomics::memory_order_acquire ) );
-                push_buffer( ep );
-            }
+            if ( p.m_p )
+                push_buffer( epoch_retired_ptr( p, m_nCurEpoch.load( atomics::memory_order_acquire )));
         }
 
         /// Retires the pointer chain [\p itFirst, \p itLast)
@@ -180,12 +178,21 @@ namespace cds { namespace urcu {
         {
             uint64_t nEpoch = m_nCurEpoch.load( atomics::memory_order_relaxed );
             while ( itFirst != itLast ) {
-                epoch_retired_ptr p( *itFirst, nEpoch );
+                push_buffer( epoch_retired_ptr( *itFirst, nEpoch ));
                 ++itFirst;
-                push_buffer( p );
             }
         }
 
+        /// Retires the pointer chain until \p Func returns \p nullptr retired pointer
+        template <typename Func>
+        void batch_retire( Func e )
+        {
+            uint64_t nEpoch = m_nCurEpoch.load( atomics::memory_order_relaxed );
+            for ( retired_ptr p{ e() }; p.m_p; p = e() )
+                push_buffer( epoch_retired_ptr( p, nEpoch ));
+        }
+
+
         /// Waits to finish a grace period and calls disposing thread
         void synchronize()
         {
index 874092ea6eeb171b23665a6b65f87b0ebfaae79f..a938b22621f9624795b16f2a6fd7a9f903cc88b2 100644 (file)
@@ -114,7 +114,7 @@ namespace cds { namespace urcu {
             }
         }
 
-        bool push_buffer( epoch_retired_ptr& ep )
+        bool push_buffer( epoch_retired_ptr&& ep )
         {
             bool bPushed = m_Buffer.push( ep );
             if ( !bPushed || m_Buffer.size() >= capacity() ) {
@@ -162,10 +162,8 @@ namespace cds { namespace urcu {
         */
         virtual void retire_ptr( retired_ptr& p )
         {
-            if ( p.m_p ) {
-                epoch_retired_ptr ep( p, m_nCurEpoch.load( atomics::memory_order_relaxed ));
-                push_buffer( ep );
-            }
+            if ( p.m_p )
+                push_buffer( epoch_retired_ptr( p, m_nCurEpoch.load( atomics::memory_order_relaxed )));
         }
 
         /// Retires the pointer chain [\p itFirst, \p itLast)
@@ -174,12 +172,20 @@ namespace cds { namespace urcu {
         {
             uint64_t nEpoch = m_nCurEpoch.load( atomics::memory_order_relaxed );
             while ( itFirst != itLast ) {
-                epoch_retired_ptr ep( *itFirst, nEpoch );
+                push_buffer( epoch_retired_ptr( *itFirst, nEpoch ));
                 ++itFirst;
-                push_buffer( ep );
             }
         }
 
+        /// Retires the pointer chain until \p Func returns \p nullptr retired pointer
+        template <typename Func>
+        void batch_retire( Func e )
+        {
+            uint64_t nEpoch = m_nCurEpoch.load( atomics::memory_order_relaxed );
+            for ( retired_ptr p{ e() }; p.m_p; p = e() )
+                push_buffer( epoch_retired_ptr( p, nEpoch ));
+        }
+
         /// Wait to finish a grace period and then clear the buffer
         void synchronize()
         {
index ffc8b49092ac44bf343aaa312a64d69e5d86199f..4471183fcb8ccd5d611275638b7f46716a6c2720 100644 (file)
@@ -105,7 +105,7 @@ namespace cds { namespace urcu {
         {}
 
         // Return: true - synchronize has been called, false - otherwise
-        bool push_buffer( epoch_retired_ptr& p )
+        bool push_buffer( epoch_retired_ptr&& p )
         {
             bool bPushed = m_Buffer.push( p );
             if ( !bPushed || m_Buffer.size() >= capacity() ) {
@@ -169,7 +169,7 @@ namespace cds { namespace urcu {
         {
             if ( p.m_p ) {
                 epoch_retired_ptr ep( p, m_nCurEpoch.load( atomics::memory_order_acquire ) );
-                push_buffer( ep );
+                push_buffer( epoch_retired_ptr( p, m_nCurEpoch.load( atomics::memory_order_acquire )));
             }
         }
 
@@ -179,12 +179,21 @@ namespace cds { namespace urcu {
         {
             uint64_t nEpoch = m_nCurEpoch.load( atomics::memory_order_relaxed );
             while ( itFirst != itLast ) {
-                epoch_retired_ptr p( *itFirst, nEpoch );
+                push_buffer( epoch_retired_ptr( *itFirst, nEpoch ) );
                 ++itFirst;
-                push_buffer( p );
             }
         }
 
+        /// Retires the pointer chain until \p Func returns \p nullptr retired pointer
+        template <typename Func>
+        void batch_retire( Func e )
+        {
+            uint64_t nEpoch = m_nCurEpoch.load( atomics::memory_order_relaxed );
+            for ( retired_ptr p{ e() }; p.m_p; p = e() )
+                push_buffer( epoch_retired_ptr( p, nEpoch ));
+        }
+
+
         /// Waits to finish a grace period and calls disposing thread
         void synchronize()
         {
index 110f395fee2df6ebbd9a4fd7dc025ec0584121ea..4f92f03f9120dffc67c1d8221c5263cb23047661 100644 (file)
@@ -101,6 +101,13 @@ namespace cds { namespace urcu {
             rcu_implementation::instance()->batch_retire( itFirst, itLast );
         }
 
+        /// Retires the pointer chain until \p Func returns \p nullptr retired pointer
+        template <typename Func>
+        static void batch_retire( Func e )
+        {
+            rcu_implementation::instance()->batch_retire( e );
+        }
+
          /// Acquires access lock (so called RCU reader-side lock)
         /**
             For safety reasons, it is better to use \ref scoped_lock class for locking/unlocking
index 9097faac74a1678066611475e3c8134938053346..c0566dca69ef54068e5b7bc4ad8f463ffb0dccc6 100644 (file)
@@ -96,6 +96,13 @@ namespace cds { namespace urcu {
             rcu_implementation::instance()->batch_retire( itFirst, itLast );
         }
 
+        /// Retires the pointer chain until \p Func returns \p nullptr retired pointer
+        template <typename Func>
+        static void batch_retire( Func e )
+        {
+            rcu_implementation::instance()->batch_retire( e );
+        }
+
         /// Acquires access lock (so called RCU reader-side lock)
         /**
             For safety reasons, it is better to use \ref scoped_lock class for locking/unlocking
index 54189aff96e81dc4b4b3c49082621d008a294fb1..e0a22ebe1f6132e6d69752eaa30c86507f0e4083 100644 (file)
@@ -107,6 +107,13 @@ namespace cds { namespace urcu {
             rcu_implementation::instance()->batch_retire( itFirst, itLast );
         }
 
+        /// Retires the pointer chain until \p Func returns \p nullptr retired pointer
+        template <typename Func>
+        static void batch_retire( Func e )
+        {
+            rcu_implementation::instance()->batch_retire( e );
+        }
+
          /// Acquires access lock (so called RCU reader-side lock)
         /**
             For safety reasons, it is better to use \ref scoped_lock class for locking/unlocking
index c9ffe3157155ff634703896d6bface98780037d6..b44f563ef61f820609ae78b65e491e64f49b1d43 100644 (file)
@@ -107,6 +107,13 @@ namespace cds { namespace urcu {
             rcu_implementation::instance()->batch_retire( itFirst, itLast );
         }
 
+        /// Retires the pointer chain until \p Func returns \p nullptr retired pointer
+        template <typename Func>
+        static void batch_retire( Func e )
+        {
+            rcu_implementation::instance()->batch_retire( e );
+        }
+
          /// Acquires access lock (so called RCU reader-side lock)
         /**
             For safety reasons, it is better to use \ref scoped_lock class for locking/unlocking
index 24d0795c28ea1c48a5c0927a3fd5a6e1a364b0a8..51e767c7bb03a0ae1ec77991fc165fc02e475737 100644 (file)
@@ -114,6 +114,13 @@ namespace cds { namespace urcu {
             rcu_implementation::instance()->batch_retire( itFirst, itLast );
         }
 
+        /// Retires the pointer chain until \p Func returns \p nullptr retired pointer
+        template <typename Func>
+        static void batch_retire( Func e )
+        {
+            rcu_implementation::instance()->batch_retire( e );
+        }
+
          /// Acquires access lock (so called RCU reader-side lock)
         /**
             For safety reasons, it is better to use \ref scoped_lock class for locking/unlocking