#ifndef __CDS_CONTAINER_MICHAEL_KVLIST_RCU_H
#define __CDS_CONTAINER_MICHAEL_KVLIST_RCU_H
+#include <memory>
#include <cds/container/michael_list_base.h>
#include <cds/intrusive/michael_list_rcu.h>
#include <cds/container/details/make_michael_kvlist.h>
#include <cds/ref.h>
#include <cds/details/functor_wrapper.h>
-#include <cds/details/std/memory.h>
namespace cds { namespace container {
cds::urcu::details::conventional_exempt_pair_cast<node_type, value_type>
> exempt_ptr;
- private:
- //@cond
-# ifndef CDS_CXX11_LAMBDA_SUPPORT
- template <typename Func>
- class insert_functor: protected cds::details::functor_wrapper<Func>
- {
- typedef cds::details::functor_wrapper<Func> base_class;
- public:
- insert_functor ( Func f )
- : base_class( f )
- {}
-
- void operator()( node_type& node )
- {
- base_class::get()( node.m_Data );
- }
- };
-
- template <typename Func>
- class ensure_functor: protected cds::details::functor_wrapper<Func>
- {
- typedef cds::details::functor_wrapper<Func> base_class;
- public:
- ensure_functor( Func f )
- : base_class(f)
- {}
-
- void operator ()( bool bNew, node_type& node, node_type& )
- {
- base_class::get()( bNew, node.m_Data );
- }
- };
-
- template <typename Func>
- class find_functor: protected cds::details::functor_wrapper<Func>
- {
- typedef cds::details::functor_wrapper<Func> base_class;
- public:
- find_functor( Func f )
- : base_class(f)
- {}
-
- template <typename Q>
- void operator ()( node_type& node, Q& )
- {
- base_class::get()( node.m_Data );
- }
- };
-
- struct empty_find_functor
- {
- template <typename Q>
- void operator ()( node_type& node, Q& val ) const
- {}
- };
-
- template <typename Func>
- struct erase_functor
- {
- Func m_func;
-
- erase_functor( Func f )
- : m_func( f )
- {}
-
- void operator ()( node_type const & node )
- {
- cds::unref(m_func)( const_cast<value_type&>(node.m_Data) );
- }
- };
-# endif // ifndef CDS_CXX11_LAMBDA_SUPPORT
- //@endcond
-
protected:
//@cond
template <typename K>
return cxx_allocator().New( key, val );
}
-# ifdef CDS_EMPLACE_SUPPORT
template <typename K, typename... Args>
static node_type * alloc_node( K&& key, Args&&... args )
{
return cxx_allocator().MoveNew( std::forward<K>(key), std::forward<Args>(args)...);
}
-# endif
static void free_node( node_type * pNode )
{
key_type const& key() const
{
typename iterator_base::value_ptr p = iterator_base::operator ->();
- assert( p != null_ptr<typename iterator_base::value_ptr>() );
+ assert( p != nullptr );
return p->m_Data.first;
}
pair_ptr operator ->() const
{
typename iterator_base::value_ptr p = iterator_base::operator ->();
- return p ? &(p->m_Data) : null_ptr<pair_ptr>();
+ return p ? &(p->m_Data) : nullptr;
}
pair_ref operator *() const
value_ref val() const
{
typename iterator_base::value_ptr p = iterator_base::operator ->();
- assert( p != null_ptr<typename iterator_base::value_ptr>() );
+ assert( p != nullptr );
return p->m_Data.second;
}
/// Returns an iterator that addresses the location succeeding the last element in a list
/**
Do not use the value returned by <tt>end</tt> function to access any item.
- Internally, <tt>end</tt> returning value equals to <tt>NULL</tt>.
+ Internally, <tt>end</tt> returning value equals to \p nullptr.
The returned value can be used only to control reaching the end of the list.
For empty list \code begin() == end() \endcode
return ensure_at( head(), key, f );
}
-# ifdef CDS_EMPLACE_SUPPORT
/// Inserts data of type \ref mapped_type constructed with <tt>std::forward<Args>(args)...</tt>
/**
Returns \p true if inserting successful, \p false otherwise.
The function makes RCU lock internally.
-
- @note This function is available only for compiler that supports
- variadic template and move semantics
*/
template <typename K, typename... Args>
bool emplace( K&& key, Args&&... args )
{
return emplace_at( head(), std::forward<K>(key), std::forward<Args>(args)... );
}
-# endif
/// Deletes \p key from the list
/** \anchor cds_nonintrusive_MichaelKVList_rcu_erase
/// Finds \p key and return the item found
/** \anchor cds_nonintrusive_MichaelKVList_rcu_get
The function searches the item with \p key and returns the pointer to item found.
- If \p key is not found it returns \p NULL.
+ If \p key is not found it returns \p nullptr.
Note the compare functor should accept a parameter of type \p K that can be not the same as \p key_type.
//@cond
bool insert_node_at( head_type& refHead, node_type * pNode )
{
- assert( pNode != null_ptr<node_type *>() );
+ assert( pNode != nullptr );
scoped_node_ptr p( pNode );
if ( base_class::insert_at( refHead, *pNode )) {
p.release();
{
scoped_node_ptr pNode( alloc_node( key ));
-# ifdef CDS_CXX11_LAMBDA_SUPPORT
- if ( base_class::insert_at( refHead, *pNode, [&f](node_type& node){ cds::unref(f)( node.m_Data ); }))
-# else
- insert_functor<Func> wrapper( f );
- if ( base_class::insert_at( refHead, *pNode, cds::ref(wrapper) ))
-# endif
- {
+ if ( base_class::insert_at( refHead, *pNode, [&f](node_type& node){ cds::unref(f)( node.m_Data ); })) {
pNode.release();
return true;
}
return false;
}
-# ifdef CDS_EMPLACE_SUPPORT
template <typename K, typename... Args>
bool emplace_at( head_type& refHead, K&& key, Args&&... args )
{
return insert_node_at( refHead, alloc_node( std::forward<K>(key), std::forward<Args>(args)... ));
}
-# endif
template <typename K, typename Func>
std::pair<bool, bool> ensure_at( head_type& refHead, const K& key, Func f )
{
scoped_node_ptr pNode( alloc_node( key ));
-# ifdef CDS_CXX11_LAMBDA_SUPPORT
std::pair<bool, bool> ret = base_class::ensure_at( refHead, *pNode,
[&f]( bool bNew, node_type& node, node_type& ){ cds::unref(f)( bNew, node.m_Data ); });
-# else
- ensure_functor<Func> wrapper( f );
- std::pair<bool, bool> ret = base_class::ensure_at( refHead, *pNode, cds::ref(wrapper));
-# endif
if ( ret.first && ret.second )
pNode.release();
template <typename K, typename Compare, typename Func>
bool erase_at( head_type& refHead, K const& key, Compare cmp, Func f )
{
-# ifdef CDS_CXX11_LAMBDA_SUPPORT
return base_class::erase_at( refHead, key, cmp, [&f]( node_type const & node ){ cds::unref(f)( const_cast<value_type&>(node.m_Data)); });
-# else
- erase_functor<Func> wrapper( f );
- return base_class::erase_at( refHead, key, cmp, cds::ref(wrapper) );
-# endif
}
template <typename K, typename Compare>
template <typename K, typename Compare>
bool find_at( head_type& refHead, K const& key, Compare cmp ) const
{
-# ifdef CDS_CXX11_LAMBDA_SUPPORT
return base_class::find_at( refHead, key, cmp, [](node_type&, K const&) {} );
-# else
- return base_class::find_at( refHead, key, cmp, empty_find_functor() );
-# endif
}
template <typename K, typename Compare, typename Func>
bool find_at( head_type& refHead, K& key, Compare cmp, Func f ) const
{
-# ifdef CDS_CXX11_LAMBDA_SUPPORT
return base_class::find_at( refHead, key, cmp, [&f](node_type& node, K const&){ cds::unref(f)( node.m_Data ); });
-# else
- find_functor<Func> wrapper( f );
- return base_class::find_at( refHead, key, cmp, cds::ref(wrapper) );
-# endif
}
template <typename K, typename Compare>
value_type * get_at( head_type& refHead, K const& val, Compare cmp ) const
{
node_type * pNode = base_class::get_at( refHead, val, cmp );
- return pNode ? &pNode->m_Data : null_ptr<value_type *>();
+ return pNode ? &pNode->m_Data : nullptr;
}
//@endcond