Uses different pass count for different parallel queue test cases
[libcds.git] / cds / gc / hp.h
index 76df6145b8d73afcf3e2c27dbf63a01bccda2834..75e8953a20c396a5d51872c041a4f5cc3c4ddadd 100644 (file)
@@ -153,7 +153,7 @@ namespace cds { namespace gc {
 #       ifdef CDS_DISABLE_SMR_EXCEPTION
                 assert( !full());
 #       else
-                if ( full() )
+                if ( full())
                     CDS_THROW_EXCEPTION( not_enought_hazard_ptr());
 #       endif
                 guard* g = free_head_;
@@ -164,7 +164,7 @@ namespace cds { namespace gc {
 
             void free( guard* g ) CDS_NOEXCEPT
             {
-                assert( g >= array_ && g < array_ + capacity() );
+                assert( g >= array_ && g < array_ + capacity());
 
                 if ( g ) {
                     g->clear();
@@ -220,7 +220,7 @@ namespace cds { namespace gc {
 
             guard& operator[]( size_t idx )
             {
-                assert( idx < capacity() );
+                assert( idx < capacity());
 
                 return array_[idx];
             }
@@ -267,14 +267,16 @@ namespace cds { namespace gc {
 
             size_t size() const CDS_NOEXCEPT
             {
-                return current_ - retired_;
+                return current_.load(atomics::memory_order_relaxed) - retired_;
             }
 
             bool push( retired_ptr&& p ) CDS_NOEXCEPT
             {
-                *current_ = p;
+                retired_ptr* cur = current_.load( atomics::memory_order_relaxed );
+                *cur = p;
                 CDS_HPSTAT( ++retire_call_count_ );
-                return ++current_ < last_;
+                current_.store( cur + 1, atomics::memory_order_relaxed );
+                return cur + 1 < last_;
             }
 
             retired_ptr* first() const CDS_NOEXCEPT
@@ -284,17 +286,22 @@ namespace cds { namespace gc {
 
             retired_ptr* last() const CDS_NOEXCEPT
             {
-                return current_;
+                return current_.load( atomics::memory_order_relaxed );
             }
 
             void reset( size_t nSize ) CDS_NOEXCEPT
             {
-                current_ = first() + nSize;
+                current_.store( first() + nSize, atomics::memory_order_relaxed );
+            }
+
+            void interthread_clear()
+            {
+                current_.exchange( first(), atomics::memory_order_acq_rel );
             }
 
             bool full() const CDS_NOEXCEPT
             {
-                return current_ == last_;
+                return current_.load( atomics::memory_order_relaxed ) == last_;
             }
 
             static size_t calc_array_size( size_t capacity )
@@ -303,9 +310,9 @@ namespace cds { namespace gc {
             }
 
         private:
-            retired_ptr*            current_;
-            retired_ptr* const      last_;
-            retired_ptr* const      retired_;
+            atomics::atomic<retired_ptr*> current_;
+            retired_ptr* const            last_;
+            retired_ptr* const            retired_;
 #       ifdef CDS_ENABLE_HPSTAT
         public:
             size_t  retire_call_count_;
@@ -386,8 +393,8 @@ namespace cds { namespace gc {
 
         /// \p smr::scan() strategy
         enum scan_type {
-            classic,    ///< classic scan as described in Michael's works (see smr::classic_scan() )
-            inplace     ///< inplace scan without allocation (see smr::inplace_scan() )
+            classic,    ///< classic scan as described in Michael's works (see smr::classic_scan())
+            inplace     ///< inplace scan without allocation (see smr::inplace_scan())
         };
 
         //@cond
@@ -514,7 +521,7 @@ namespace cds { namespace gc {
 #       ifdef CDS_DISABLE_SMR_EXCEPTION
                     assert( false );    // not enough hazard ptr
 #       else
-                    CDS_THROW_EXCEPTION( not_enought_hazard_ptr() );
+                    CDS_THROW_EXCEPTION( not_enought_hazard_ptr());
 #       endif
                 }
             }
@@ -526,7 +533,7 @@ namespace cds { namespace gc {
             static CDS_EXPORT_API void detach_thread();
 
             /// Get internal statistics
-            void statistics( stat& st );
+            CDS_EXPORT_API void statistics( stat& st );
 
         public: // for internal use only
             /// The main garbage collecting function
@@ -691,7 +698,7 @@ namespace cds { namespace gc {
                 @warning Can throw \p too_many_hazard_ptr_exception if internal hazard pointer objects are exhausted.
             */
             Guard()
-                : guard_( hp::smr::tls()->hazards_.alloc() )
+                : guard_( hp::smr::tls()->hazards_.alloc())
             {}
 
             /// Initilalizes an unlinked guard i.e. the guard contains no hazard pointer. Used for move semantics support
@@ -999,7 +1006,7 @@ namespace cds { namespace gc {
             template <typename T>
             T * assign( size_t nIndex, T * p )
             {
-                assert( nIndex < capacity() );
+                assert( nIndex < capacity());
 
                 guards_.set( nIndex, p );
                 hp::smr::tls()->sync();
@@ -1039,7 +1046,7 @@ namespace cds { namespace gc {
             template <typename T>
             T * get( size_t nIndex ) const
             {
-                assert( nIndex < capacity() );
+                assert( nIndex < capacity());
                 return guards_[nIndex]->template get_as<T>();
             }
 
@@ -1374,7 +1381,7 @@ namespace cds { namespace gc {
             \p func is a disposer: when \p p can be safely removed, \p func is called.
         */
         template <typename T>
-        static void retire( T * p, void( *func )( T * ))
+        static void retire( T * p, void( *func )( void * ))
         {
             hp::thread_data* rec = hp::smr::tls();
             if ( !rec->retired_.push( hp::retired_ptr( p, func )))
@@ -1469,7 +1476,7 @@ namespace cds { namespace gc {
             The function clears \p st before gathering statistics.
 
             @note Internal statistics is available only if you compile
-            \p libcds and your program with \p -DCDS_ENABLE_HPSTAT key.
+            \p libcds and your program with \p -DCDS_ENABLE_HPSTAT.
         */
         static void statistics( stat& st )
         {
@@ -1482,7 +1489,7 @@ namespace cds { namespace gc {
             and can be accessible after destructing the global \p %HP object.
 
             @note Internal statistics is available only if you compile
-            \p libcds and your program with \p -DCDS_ENABLE_HPSTAT key.
+            \p libcds and your program with \p -DCDS_ENABLE_HPSTAT.
 
             Usage:
             \code
@@ -1519,7 +1526,7 @@ namespace cds { namespace gc {
             }
             \endcode
         */
-        static stat const& postmortem_statistics();
+        CDS_EXPORT_API static stat const& postmortem_statistics();
     };
 
 }} // namespace cds::gc