Merge branch 'dev' into integration
[libcds.git] / cds / container / michael_list_nogc.h
index 64af875f6e1180095f738945478beade817a58d2..1bf897c7203c4f3bd00302e4c83eeeea780b85c7 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_CONTAINER_MICHAEL_LIST_NOGC_H
 #define CDSLIB_CONTAINER_MICHAEL_LIST_NOGC_H
@@ -70,6 +98,7 @@ namespace cds { namespace container {
         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
+        typedef typename base_class::stat         stat;           ///< Internal statistics
 
     protected:
         //@cond
@@ -194,6 +223,8 @@ namespace cds { namespace container {
         //@endcond
 
     public:
+   ///@name Forward iterators
+   //@{
         /// Returns a forward iterator addressing the first element in a list
         /**
             For empty list \code begin() == end() \endcode
@@ -229,28 +260,29 @@ namespace cds { namespace container {
         }
 
         /// Returns a forward const iterator addressing the first element in a list
-        //@{
         const_iterator begin() const
         {
             return const_iterator( head() );
         }
+
+        /// Returns a forward const iterator addressing the first element in a list
         const_iterator cbegin() const
         {
             return const_iterator( head() );
         }
-        //@}
 
         /// Returns an const iterator that addresses the location succeeding the last element in a list
-        //@{
         const_iterator end() const
         {
             return const_iterator();
         }
+
+        /// Returns an const iterator that addresses the location succeeding the last element in a list
         const_iterator cend() const
         {
             return const_iterator();
         }
-        //@}
+    //@}
 
     protected:
         //@cond
@@ -270,7 +302,14 @@ namespace cds { namespace container {
         MichaelList()
         {}
 
-        /// List desctructor
+        //@cond
+        template <typename Stat, typename = std::enable_if<std::is_same<stat, michael_list::wrapped_stat<Stat>>::value >>
+        explicit MichaelList( Stat& st )
+            : base_class( st )
+        {}
+        //@endcond
+
+        /// List destructor
         /**
             Clears the list
         */
@@ -292,21 +331,30 @@ namespace cds { namespace container {
             return node_to_iterator( insert_at( head(), val ) );
         }
 
-        /// Ensures that the item \p val exists in the list
+        /// Updates the item
         /**
-            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.
+            If \p key is not in the list and \p bAllowInsert is \p true,
+            the function inserts a new item.
+            Otherwise, the function returns an iterator pointing to the 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.
         */
         template <typename Q>
-        std::pair<iterator, bool> ensure( const Q& val )
+        std::pair<iterator, bool> update( const Q& key, bool bAllowInsert = true )
         {
-            std::pair< node_type *, bool > ret = ensure_at( head(), val );
+            std::pair< node_type *, bool > ret = update_at( head(), key, bAllowInsert );
             return std::make_pair( node_to_iterator( ret.first ), ret.second );
         }
+        //@cond
+        template <typename Q>
+        CDS_DEPRECATED("ensure() is deprecated, use update()")
+        std::pair<iterator, bool> ensure( const Q& val )
+        {
+            return update( val, true );
+        }
+        //@endcond
 
         /// Inserts data of type \ref value_type constructed with <tt>std::forward<Args>(args)...</tt>
         /**
@@ -318,31 +366,46 @@ namespace cds { namespace container {
             return node_to_iterator( emplace_at( head(), std::forward<Args>(args)... ));
         }
 
-        /// Find the key \p key
-        /** \anchor cds_nonintrusive_MichaelList_nogc_find_val
+        /// Checks whether the list contains \p key
+        /**
             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 \p end() otherwise
+            and \ref end() otherwise
         */
         template <typename Q>
-        iterator find( Q const& key )
+        iterator contains( Q const& key )
         {
             return node_to_iterator( find_at( head(), key, intrusive_key_comparator() ));
         }
+        //@cond
+        template <typename Q>
+        CDS_DEPRECATED("deprecated, use contains()")
+        iterator find( Q const& key )
+        {
+            return contains( key );
+        }
+        //@endcond
 
-        /// Finds the key \p key using \p pred predicate for searching
+        /// Checks whether the map contains \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.
+            The function is an analog of <tt>contains( key )</tt> but \p pred is used for key comparing.
             \p Less functor has the interface like \p std::less.
-            \p pred must imply the same element order as the comparator used for building the list.
+            \p Less must imply the same element order as the comparator used for building the list.
         */
         template <typename Q, typename Less>
-        iterator find_with( Q const& key, Less pred )
+        iterator contains( Q const& key, Less pred )
         {
             CDS_UNUSED( pred );
             return node_to_iterator( find_at( head(), key, typename maker::template less_wrapper<Less>::type() ) );
         }
+        //@cond
+        template <typename Q, typename Less>
+        CDS_DEPRECATED("deprecated, use contains()")
+        iterator find_with( Q const& key, Less pred )
+        {
+            return contains( key, pred );
+        }
+        //@endcond
 
         /// Check if the list is empty
         bool empty() const
@@ -363,6 +426,12 @@ namespace cds { namespace container {
             return base_class::size();
         }
 
+        /// Returns const reference to internal statistics
+        stat const& statistics() const
+        {
+            return base_class::statistics();
+        }
+
         /// Clears the list
         void clear()
         {
@@ -371,6 +440,16 @@ namespace cds { namespace container {
 
     protected:
         //@cond
+        static value_type& node_to_value( node_type& n )
+        {
+            return n.m_Value;
+        }
+
+        iterator insert_node( node_type * pNode )
+        {
+            return node_to_iterator( insert_node_at( head(), pNode ));
+        }
+
         node_type * insert_node_at( head_type& refHead, node_type * pNode )
         {
             assert( pNode != nullptr );
@@ -388,15 +467,16 @@ namespace cds { namespace container {
         }
 
         template <typename Q>
-        std::pair< node_type *, bool > ensure_at( head_type& refHead, const Q& val )
+        std::pair< node_type *, bool > update_at( head_type& refHead, const Q& val, bool bAllowInsert )
         {
             scoped_node_ptr pNode( alloc_node( val ));
             node_type * pItemFound = nullptr;
 
-            std::pair<bool, bool> ret = base_class::ensure_at( refHead, *pNode, [&pItemFound](bool, node_type& item, node_type&) { pItemFound = &item; });
-            assert( pItemFound != nullptr );
+            std::pair<bool, bool> ret = base_class::update_at( refHead, *pNode,
+                [&pItemFound](bool, node_type& item, node_type&) { pItemFound = &item; },
+                bAllowInsert );
 
-            if ( ret.first && ret.second )
+            if ( ret.second )
                 pNode.release();
             return std::make_pair( pItemFound, ret.second );
         }