movable exempt_ptr: MichaelList
[libcds.git] / cds / container / michael_list_nogc.h
index 512d61737a997a62ba10caf01fcaeccf58efb3f8..3c57529f2a915c47149c3d2ace435d2b85f890a4 100644 (file)
@@ -4,7 +4,7 @@
 #define __CDS_CONTAINER_MICHAEL_LIST_NOGC_H
 
 #include <memory>
-#include <cds/container/michael_list_base.h>
+#include <cds/container/details/michael_list_base.h>
 #include <cds/intrusive/michael_list_nogc.h>
 #include <cds/container/details/make_michael_list.h>
 
@@ -19,31 +19,35 @@ namespace cds { namespace container {
             typedef make_michael_list<cds::gc::nogc, T, Traits>  base_maker;
             typedef typename base_maker::node_type node_type;
 
-            struct type_traits: public base_maker::type_traits
+            struct intrusive_traits: public base_maker::intrusive_traits
             {
                 typedef typename base_maker::node_deallocator    disposer;
             };
 
-            typedef intrusive::MichaelList<cds::gc::nogc, node_type, type_traits>  type;
+            typedef intrusive::MichaelList<cds::gc::nogc, node_type, intrusive_traits>  type;
         };
 
     }   // namespace details
     //@endcond
 
-    /// Michael's lock-free ordered single-linked list (template specialization for gc::nogc)
+    /// Michael's lock-free ordered single-linked list (template specialization for \p gc::nogc)
     /** @ingroup cds_nonintrusive_list
         \anchor cds_nonintrusive_MichaelList_nogc
 
-        This specialization is intended for so-called persistent usage when no item
+        This specialization is intended for so-called append-only usage when no item
         reclamation may be performed. The class does not support deleting of list item.
         Usually, ordered single-linked list is used as a building block for the hash table implementation.
         The complexity of searching is <tt>O(N)</tt>.
 
         See \ref cds_nonintrusive_MichaelList_gc "MichaelList" for description of template parameters.
-
-        The interface of the specialization is a little different.
     */
-    template <typename T, typename Traits>
+    template <typename T,
+#ifdef CDS_DOXYGEN_INVOKED
+        class Traits = michael_list::traits
+#else
+        class Traits
+#endif
+    >
     class MichaelList<gc::nogc, T, Traits>:
 #ifdef CDS_DOXYGEN_INVOKED
         protected intrusive::MichaelList< gc::nogc, T, Traits >
@@ -52,46 +56,29 @@ namespace cds { namespace container {
 #endif
     {
         //@cond
-        typedef details::make_michael_list_nogc< T, Traits > options;
-        typedef typename options::type  base_class;
+        typedef details::make_michael_list_nogc< T, Traits > maker;
+        typedef typename maker::type  base_class;
         //@endcond
 
     public:
-        typedef T                                   value_type      ;   ///< Type of value stored in the list
-        typedef typename base_class::gc             gc              ;   ///< Garbage collector used
-        typedef typename base_class::back_off       back_off        ;   ///< Back-off strategy used
-        typedef typename options::allocator_type    allocator_type  ;   ///< Allocator type used for allocate/deallocate the nodes
-        typedef typename base_class::item_counter   item_counter    ;   ///< Item counting policy used
-        typedef typename options::key_comparator    key_comparator  ;   ///< key comparison functor
-        typedef typename base_class::memory_model   memory_model    ;   ///< Memory ordering. See cds::opt::memory_model option
+        typedef cds::gc::nogc gc;         ///< Garbage collector used
+        typedef T             value_type; ///< Type of value stored in the list
+        typedef Traits        traits;     ///< List traits
 
-    protected:
-        //@cond
-        typedef typename base_class::value_type     node_type;
-        typedef typename options::cxx_allocator     cxx_allocator;
-        typedef typename options::node_deallocator  node_deallocator;
-        typedef typename options::type_traits::compare  intrusive_key_comparator;
-
-        typedef typename base_class::atomic_node_ptr head_type;
-        //@endcond
+        typedef typename base_class::back_off     back_off;       ///< Back-off strategy used
+        typedef typename maker::allocator_type    allocator_type; ///< Allocator type used for allocate/deallocate the nodes
+        typedef typename base_class::item_counter item_counter;   ///< Item counting policy used
+        typedef typename maker::key_comparator    key_comparator; ///< key comparison functor
+        typedef typename base_class::memory_model memory_model;   ///< Memory ordering. See cds::opt::memory_model option
 
     protected:
         //@cond
-#   ifndef CDS_CXX11_LAMBDA_SUPPORT
-        struct ensure_functor
-        {
-            node_type * m_pItemFound;
-
-            ensure_functor()
-                : m_pItemFound( nullptr )
-            {}
+        typedef typename base_class::value_type   node_type;
+        typedef typename maker::cxx_allocator     cxx_allocator;
+        typedef typename maker::node_deallocator  node_deallocator;
+        typedef typename maker::intrusive_traits::compare  intrusive_key_comparator;
 
-            void operator ()(bool, node_type& item, node_type& )
-            {
-                m_pItemFound = &item;
-            }
-        };
-#   endif
+        typedef typename base_class::atomic_node_ptr head_type;
         //@endcond
 
     protected:
@@ -247,7 +234,7 @@ namespace cds { namespace container {
         {
             return const_iterator( head() );
         }
-        const_iterator cbegin()
+        const_iterator cbegin() const
         {
             return const_iterator( head() );
         }
@@ -259,7 +246,7 @@ namespace cds { namespace container {
         {
             return const_iterator();
         }
-        const_iterator cend()
+        const_iterator cend() const
         {
             return const_iterator();
         }
@@ -310,7 +297,7 @@ namespace cds { namespace container {
             The operation inserts new item if the key \p val is not found in the list.
             Otherwise, the function returns an iterator that points to item found.
 
-            Returns <tt> std::pair<iterator, bool>  </tt> where \p first is an iterator pointing to
+            Returns <tt> std::pair<iterator, bool> </tt> where \p first is an iterator pointing to
             item found or inserted, \p second is true if new item has been added or \p false if the item
             already is in the list.
         */
@@ -331,11 +318,11 @@ namespace cds { namespace container {
             return node_to_iterator( emplace_at( head(), std::forward<Args>(args)... ));
         }
 
-        /// Find the key \p val
+        /// Find the key \p key
         /** \anchor cds_nonintrusive_MichaelList_nogc_find_val
-            The function searches the item with key equal to \p val
+            The function searches the item with key equal to \p key
             and returns an iterator pointed to item found if the key is found,
-            and \ref end() otherwise
+            and \p end() otherwise
         */
         template <typename Q>
         iterator find( Q const& key )
@@ -343,7 +330,7 @@ namespace cds { namespace container {
             return node_to_iterator( find_at( head(), key, intrusive_key_comparator() ));
         }
 
-        /// Finds the key \p val using \p pred predicate for searching
+        /// Finds the key \p key using \p pred predicate for searching
         /**
             The function is an analog of \ref cds_nonintrusive_MichaelList_nogc_find_val "find(Q const&)"
             but \p pred is used for key comparing.
@@ -353,7 +340,7 @@ namespace cds { namespace container {
         template <typename Q, typename Less>
         iterator find_with( Q const& key, Less pred )
         {
-            return node_to_iterator( find_at( head(), key, typename options::template less_wrapper<Less>::type() ));
+            return node_to_iterator( find_at( head(), key, typename maker::template less_wrapper<Less>::type() ) );
         }
 
         /// Check if the list is empty
@@ -364,11 +351,11 @@ namespace cds { namespace container {
 
         /// Returns list's item count
         /**
-            The value returned depends on opt::item_counter option. For atomics::empty_item_counter,
+            The value returned depends on item counter provided by \p Traits. For \p atomicity::empty_item_counter,
             this function always returns 0.
 
-            <b>Warning</b>: even if you use real item counter and it returns 0, this fact is not mean that the list
-            is empty. To check list emptyness use \ref empty() method.
+            @note Even if you use real item counter and it returns 0, this fact does not mean that the list
+            is empty. To check list emptyness use \p empty() method.
         */
         size_t size() const
         {
@@ -376,9 +363,6 @@ namespace cds { namespace container {
         }
 
         /// Clears the list
-        /**
-            Post-condition: the list is empty
-        */
         void clear()
         {
             base_class::clear();
@@ -408,13 +392,7 @@ namespace cds { namespace container {
             scoped_node_ptr pNode( alloc_node( val ));
             node_type * pItemFound = nullptr;
 
-#   ifdef CDS_CXX11_LAMBDA_SUPPORT
             std::pair<bool, bool> ret = base_class::ensure_at( refHead, *pNode, [&pItemFound](bool, node_type& item, node_type&) { pItemFound = &item; });
-#   else
-            ensure_functor func;
-            std::pair<bool, bool> ret = base_class::ensure_at( refHead, *pNode, boost::ref(func) );
-            pItemFound = func.m_pItemFound;
-#   endif
             assert( pItemFound != nullptr );
 
             if ( ret.first && ret.second )