Removed redundant spaces
[libcds.git] / cds / gc / details / hp.h
index 6820e2552ac05985a87ec114a82e6627738aefba..cfd68b9348a6b2f9101faf09283483617a43e765 100644 (file)
@@ -1,4 +1,32 @@
-//$$CDS-header$$
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    Source code repo: http://github.com/khizmax/libcds/
+    Download: http://sourceforge.net/projects/libcds/files/
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, this
+      list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
 
 #ifndef CDSLIB_GC_DETAILS_HP_H
 #define CDSLIB_GC_DETAILS_HP_H
@@ -6,6 +34,7 @@
 #include <cds/algo/atomic.h>
 #include <cds/os/thread.h>
 #include <cds/details/bounded_array.h>
+#include <cds/user_setup/cache_line.h>
 
 #include <cds/gc/details/hp_type.h>
 #include <cds/gc/details/hp_alloc.h>
@@ -105,19 +134,19 @@ namespace cds {
                 /// Set vector size. Uses internally
                 void size( size_t nSize )
                 {
-                    assert( nSize <= capacity() );
+                    assert( nSize <= capacity());
                     m_nSize = nSize;
                 }
 
                 /// Pushes retired pointer to the vector
                 void push( retired_ptr const& p )
                 {
-                    assert( m_nSize < capacity() );
+                    assert( m_nSize < capacity());
                     m_arr[ m_nSize ] = p;
                     ++m_nSize;
                 }
 
-                /// Checks if the vector is full (size() == capacity() )
+                /// Checks if the vector is full (size() == capacity())
                 bool isFull() const CDS_NOEXCEPT
                 {
                     return m_nSize >= capacity();
@@ -148,11 +177,15 @@ namespace cds {
                 other threads have read-only access.
             */
             struct hp_record {
-                hp_allocator<>    m_hzp; ///< array of hazard pointers. Implicit \ref CDS_DEFAULT_ALLOCATOR dependency
+                hp_allocator<>    m_hzp;         ///< array of hazard pointers. Implicit \ref CDS_DEFAULT_ALLOCATOR dependency
                 retired_vector    m_arrRetired ; ///< Retired pointer array
 
+                char padding[cds::c_nCacheLineSize];
+                atomics::atomic<unsigned int> m_nSync; ///< dummy var to introduce synchronizes-with relationship between threads
+                char padding2[cds::c_nCacheLineSize];
+
                 /// Ctor
-                hp_record( const cds::gc::hp::GarbageCollector& HzpMgr );    // inline
+                hp_record( const cds::gc::hp::GarbageCollector& HzpMgr ); // inline
                 ~hp_record()
                 {}
 
@@ -161,6 +194,11 @@ namespace cds {
                 {
                     m_hzp.clear();
                 }
+
+                void sync()
+                {
+                    m_nSync.fetch_add( 1, atomics::memory_order_acq_rel );
+                }
             };
         }    // namespace details
 
@@ -224,13 +262,13 @@ namespace cds {
                 //@endcond
             };
 
-            /// Not enough required Hazard Pointer count
+            /// Not enough Hazard Pointer
             class too_many_hazard_ptr : public std::length_error
             {
             public:
                 //@cond
                 too_many_hazard_ptr()
-                    : std::length_error( "Not enough required Hazard Pointer count" )
+                    : std::length_error( "Not enough Hazard Pointer" )
                 {}
                 //@endcond
             };
@@ -269,9 +307,9 @@ namespace cds {
                 ~hplist_node()
                 {
                     assert( m_idOwner.load( atomics::memory_order_relaxed ) == OS::c_NullThreadId );
-                    assert( m_bFree.load(atomics::memory_order_relaxed) );
+                    assert( m_bFree.load(atomics::memory_order_relaxed));
                 }
-                               //@endcond
+                //@endcond
             };
 
             atomics::atomic<hplist_node *>   m_pListHead  ;  ///< Head of GC list
@@ -424,10 +462,10 @@ namespace cds {
         public:    // Internals for threads
 
             /// Allocates Hazard Pointer GC record. For internal use only
-            details::hp_record * alloc_hp_record();
+            details::hp_record* alloc_hp_record();
 
             /// Free HP record. For internal use only
-            void free_hp_record( details::hp_record * pRec );
+            void free_hp_record( details::hp_record* pRec );
 
             /// The main garbage collecting function
             /**
@@ -509,13 +547,13 @@ namespace cds {
         */
         class ThreadGC
         {
-            GarbageCollector&    m_HzpManager; ///< Hazard Pointer GC singleton
-            details::hp_record * m_pHzpRec;    ///< Pointer to thread's HZP record
+            GarbageCollector&   m_HzpManager; ///< Hazard Pointer GC singleton
+            details::hp_record* m_pHzpRec;    ///< Pointer to thread's HZP record
 
         public:
             /// Default constructor
             ThreadGC()
-                : m_HzpManager( GarbageCollector::instance() ),
+                : m_HzpManager( GarbageCollector::instance()),
                 m_pHzpRec( nullptr )
             {}
 
@@ -528,7 +566,7 @@ namespace cds {
             }
 
             /// Checks if thread GC is initialized
-            bool    isInitialized() const   { return m_pHzpRec != nullptr; }
+            bool isInitialized() const   { return m_pHzpRec != nullptr; }
 
             /// Initialization. Repeat call is available
             void init()
@@ -541,21 +579,21 @@ namespace cds {
             void fini()
             {
                 if ( m_pHzpRec ) {
-                    details::hp_record * pRec = m_pHzpRec;
+                    details::hp_record* pRec = m_pHzpRec;
                     m_pHzpRec = nullptr;
                     m_HzpManager.free_hp_record( pRec );
                 }
             }
 
             /// Initializes HP guard \p guard
-            details::hp_guard& allocGuard()
+            details::hp_guard* allocGuard()
             {
                 assert( m_pHzpRec );
                 return m_pHzpRec->m_hzp.alloc();
             }
 
             /// Frees HP guard \p guard
-            void freeGuard( details::hp_guard& guard )
+            void freeGuard( details::hp_guard* guard )
             {
                 assert( m_pHzpRec );
                 m_pHzpRec->m_hzp.free( guard );
@@ -563,10 +601,10 @@ namespace cds {
 
             /// Initializes HP guard array \p arr
             template <size_t Count>
-            void allocGuard( details::hp_array<Count>& arr )
+            size_t allocGuard( details::hp_array<Count>& arr )
             {
                 assert( m_pHzpRec );
-                m_pHzpRec->m_hzp.alloc( arr );
+                return m_pHzpRec->m_hzp.alloc( arr );
             }
 
             /// Frees HP guard array \p arr
@@ -579,23 +617,8 @@ namespace cds {
 
             /// Places retired pointer \p and its deleter \p pFunc into thread's array of retired pointer for deferred reclamation
             template <typename T>
-            void retirePtr( T * p, void (* pFunc)(T *) )
+            void retirePtr( T * p, void (* pFunc)(T *))
             {
-                /*
-                union {
-                    T * p;
-                    hazard_pointer hp;
-                } cast_ptr;
-                cast_ptr.p = p;
-
-                union{
-                    void( *pFunc )(T *);
-                    free_retired_ptr_func hpFunc;
-                } cast_func;
-                cast_func.pFunc = pFunc;
-
-                retirePtr( details::retired_ptr( cast_ptr.hp, cast_func.hpFunc ) );
-                */
                 retirePtr( details::retired_ptr( reinterpret_cast<void *>( p ), reinterpret_cast<free_retired_ptr_func>( pFunc )));
             }
 
@@ -604,7 +627,7 @@ namespace cds {
             {
                 m_pHzpRec->m_arrRetired.push( p );
 
-                if ( m_pHzpRec->m_arrRetired.isFull() ) {
+                if ( m_pHzpRec->m_arrRetired.isFull()) {
                     // Max of retired pointer count is reached. Do scan
                     scan();
                 }
@@ -616,76 +639,14 @@ namespace cds {
                 m_HzpManager.Scan( m_pHzpRec );
                 m_HzpManager.HelpScan( m_pHzpRec );
             }
-        };
 
-        /// Auto hp_guard.
-        /**
-            This class encapsulates Hazard Pointer guard to protect a pointer against deletion .
-            It allocates one HP from thread's HP array in constructor and free the hazard pointer allocated
-            in destructor.
-        */
-        class guard
-        {
-            details::hp_guard&  m_hp    ; ///< Hazard pointer guarded
-
-        public:
-            typedef details::hp_guard::hazard_ptr hazard_ptr ;  ///< Hazard pointer type
-
-        public:
-            /// Allocates HP guard
-            guard(); // inline in hp_impl.h
-
-            /// Allocates HP guard from \p gc and protects the pointer \p p of type \p T
-            template <typename T>
-            explicit guard( T * p ); // inline in hp_impl.h
-
-            /// Frees HP guard. The pointer guarded may be deleted after this.
-            ~guard(); // inline in hp_impl.h
-
-            /// Protects the pointer \p p against reclamation (guards the pointer).
-            template <typename T>
-            T * operator =( T * p )
-            {
-                return m_hp = p;
-            }
-
-            //@cond
-            std::nullptr_t operator =(std::nullptr_t)
-            {
-                return m_hp = nullptr;
-            }
-            //@endcond
-
-            /// Get raw guarded pointer
-            hazard_ptr get() const
+            void sync()
             {
-                return m_hp;
+                assert( m_pHzpRec != nullptr );
+                m_pHzpRec->sync();
             }
         };
 
-        /// Auto-managed array of hazard pointers
-        /**
-            This class is wrapper around cds::gc::hp::details::hp_array class.
-            \p Count is the size of HP array
-        */
-        template <size_t Count>
-        class array : public details::hp_array<Count>
-        {
-        public:
-            /// Rebind array for other size \p COUNT2
-            template <size_t Count2>
-            struct rebind {
-                typedef array<Count2>  other;   ///< rebinding result
-            };
-
-        public:
-            /// Allocates array of HP guard
-            array(); // inline in hp_impl.h
-
-            /// Frees array of HP guard
-            ~array(); //inline in hp_impl.h
-        };
-
     }   // namespace hp
 }}  // namespace cds::gc
 //@endcond
@@ -696,13 +657,14 @@ namespace cds {
     namespace gc { namespace hp { namespace details {
 
         inline retired_vector::retired_vector( const cds::gc::hp::GarbageCollector& HzpMgr )
-            : m_arr( HzpMgr.getMaxRetiredPtrCount() ),
+            : m_arr( HzpMgr.getMaxRetiredPtrCount()),
             m_nSize(0)
         {}
 
         inline hp_record::hp_record( const cds::gc::hp::GarbageCollector& HzpMgr )
-            : m_hzp( HzpMgr.getHazardPointerCount() ),
-            m_arrRetired( HzpMgr )
+            : m_hzp( HzpMgr.getHazardPointerCount())
+            , m_arrRetired( HzpMgr )
+            , m_nSync( 0 )
         {}
 
     }}} // namespace gc::hp::details