CMake build system introduced (issue #9)
[libcds.git] / src / dhp_gc.cpp
index b17d0e610cb45e00912545af72468e65929790fd..ea41aa14fac9604bc73d1395b863f75cbbcf4a30 100644 (file)
@@ -1,14 +1,14 @@
 //$$CDS-header$$
 
-// Pass The Buck (PTB) Memory manager implementation
+// Dynamic Hazard Pointer memory manager implementation
 
 #include <algorithm>   // std::fill
 #include <functional>  // std::hash
 
-#include <cds/gc/dhp/dhp.h>
+#include <cds/gc/details/dhp.h>
 #include <cds/algo/int_algo.h>
 
-namespace cds { namespace gc { namespace ptb {
+namespace cds { namespace gc { namespace dhp {
 
     namespace details {
 
@@ -147,10 +147,8 @@ namespace cds { namespace gc { namespace ptb {
 
     void CDS_STDCALL GarbageCollector::Destruct()
     {
-        if ( m_pManager ) {
-            delete m_pManager;
-            m_pManager = nullptr;
-        }
+        delete m_pManager;
+        m_pManager = nullptr;
     }
 
     GarbageCollector::GarbageCollector( size_t nLiberateThreshold, size_t nInitialThreadGuardCount )
@@ -162,32 +160,10 @@ namespace cds { namespace gc { namespace ptb {
 
     GarbageCollector::~GarbageCollector()
     {
-        liberate();
-
-#if 0
-        details::retired_ptr_node * pHead = nullptr;
-        details::retired_ptr_node * pTail = nullptr;
-
-        for ( details::guard_data * pGuard = m_GuardPool.begin(); pGuard; pGuard = pGuard->pGlobalNext.load(atomics::memory_order_relaxed)) {
-            details::guard_data::handoff_ptr h = pGuard->pHandOff;
-            pGuard->pHandOff  = nullptr;
-            while ( h ) {
-                details::guard_data::handoff_ptr pNext = h->m_pNextFree;
-                if ( h->m_ptr.m_p )
-                    h->m_ptr.free();
-                if ( !pHead )
-                    pTail = pHead = h;
-                else
-                    pTail = pTail->m_pNextFree = h;
-                h = pNext;
-            }
-        }
-        if ( pHead )
-            m_RetiredAllocator.free_range( pHead, pTail );
-#endif
+        scan();
     }
 
-    void GarbageCollector::liberate()
+    void GarbageCollector::scan()
     {
         details::retired_ptr_buffer::privatize_result retiredList = m_RetiredBuffer.privatize();
         if ( retiredList.first ) {
@@ -205,6 +181,11 @@ namespace cds { namespace gc { namespace ptb {
             }
 
             // Liberate cycle
+
+            details::retired_ptr_node * pBusyFirst = nullptr;
+            details::retired_ptr_node * pBusyLast = nullptr;
+            size_t nBusyCount = 0;
+
             for ( details::guard_data * pGuard = m_GuardPool.begin(); pGuard; pGuard = pGuard->pGlobalNext.load(atomics::memory_order_acquire) )
             {
                 // get guarded pointer
@@ -217,15 +198,24 @@ namespace cds { namespace gc { namespace ptb {
                         // pRetired is the head of retired pointers list for which the m_ptr.m_p field is equal
                         // List is linked on m_pNextFree field
 
-                        do {
-                            details::retired_ptr_node * pNext = pRetired->m_pNextFree;
-                            m_RetiredBuffer.push( *pRetired );
-                            pRetired = pNext;
-                        } while ( pRetired );
+                        if ( pBusyLast )
+                            pBusyLast->m_pNext = pRetired;
+                        else
+                            pBusyFirst = pRetired;
+                        pBusyLast = pRetired;
+                        ++nBusyCount;
+                        while ( pBusyLast->m_pNextFree ) {
+                            pBusyLast = pBusyLast->m_pNext = pBusyLast->m_pNextFree;
+                            ++nBusyCount;
+                        }
                     }
                 }
             }
 
+            // Place [pBusyList, pBusyLast] back to m_RetiredBuffer
+            if ( pBusyFirst )
+                m_RetiredBuffer.push_list( pBusyFirst, pBusyLast, nBusyCount );
+
             // Free all retired pointers
             details::liberate_set::list_range range = set.free_all();
 
@@ -236,72 +226,9 @@ namespace cds { namespace gc { namespace ptb {
                 m_RetiredAllocator.free_range( range.first, range.second );
             }
             else {
-                // liberate cycle did not free any retired pointer - double liberate threshold
+                // scan() cycle did not free any retired pointer - double scan() threshold
                 m_nLiberateThreshold.compare_exchange_strong( nLiberateThreshold, nLiberateThreshold * 2, atomics::memory_order_release, atomics::memory_order_relaxed );
             }
         }
     }
-
-#if 0
-    void GarbageCollector::liberate( details::liberate_set& set )
-    {
-        details::guard_data::handoff_ptr const nullHandOff = nullptr;
-
-        for ( details::guard_data * pGuard = m_GuardPool.begin(); pGuard; pGuard = pGuard->pGlobalNext.load(atomics::memory_order_acquire) )
-        {
-            // get guarded pointer
-            details::guard_data::guarded_ptr  valGuarded = pGuard->pPost.load(atomics::memory_order_acquire);
-            details::guard_data::handoff_ptr h;
-
-            if ( valGuarded ) {
-                details::retired_ptr_node * pRetired = set.erase( valGuarded );
-                if ( pRetired ) {
-                    // Retired pointer is being guarded
-
-                    // pRetired is the head of retired pointers list for which the m_ptr.m_p field is equal
-                    // List is linked on m_pNextFree field
-
-                    // Now, try to set retired node pRetired as a hand-off node for the guard
-                    cds::lock::Auto<details::guard_data::handoff_spin> al( pGuard->spinHandOff );
-                    if ( valGuarded == pGuard->pPost.load(atomics::memory_order_acquire) ) {
-                        if ( pGuard->pHandOff && pGuard->pHandOff->m_ptr.m_p == pRetired->m_ptr.m_p ) {
-                            h = nullHandOff ; //nullptr;
-                            details::retired_ptr_node * pTail = pGuard->pHandOff;
-                            while ( pTail->m_pNextFree )
-                                pTail = pTail->m_pNextFree;
-                            pTail->m_pNextFree = pRetired;
-                        }
-                        else {
-                            // swap h and pGuard->pHandOff
-                            h = pGuard->pHandOff;
-                            pGuard->pHandOff = pRetired;
-                        }
-                    }
-                    else
-                        h = pRetired;
-                }
-                else {
-                    cds::lock::Auto<details::guard_data::handoff_spin> al( pGuard->spinHandOff );
-                    h = pGuard->pHandOff;
-                    if ( h ) {
-                        if ( h->m_ptr.m_p != valGuarded )
-                            pGuard->pHandOff = nullHandOff;
-                        else
-                            h = nullHandOff;
-                    }
-                }
-            }
-            else {
-                cds::lock::Auto<details::guard_data::handoff_spin> al( pGuard->spinHandOff );
-                h = pGuard->pHandOff;
-                pGuard->pHandOff = nullHandOff;
-            }
-
-            // h is the head of a list linked on m_pNextFree field
-            if ( h ) {
-                set.insert( *h );
-            }
-        }
-    }
-#endif
-}}} // namespace cds::gc::ptb
+}}} // namespace cds::gc::dhp