From fa32cf17b6f47caa89d15bd5eff197f68e0b4c2d Mon Sep 17 00:00:00 2001 From: khizmax Date: Thu, 17 Mar 2016 22:49:22 +0300 Subject: [PATCH] Fixed serious bug in MichaelSet::emplace() function New node was created twice from the arguments by move semantics. However, move semantics may change internal state of the argument. This can lead to an incorrect element in the set and even to an incorrect key that breaks the set logic. --- cds/container/impl/lazy_list.h | 11 +++++++---- cds/container/lazy_list_nogc.h | 10 ++++++++++ cds/container/lazy_list_rcu.h | 11 +++++++---- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/cds/container/impl/lazy_list.h b/cds/container/impl/lazy_list.h index 45ddb68e..541f2453 100644 --- a/cds/container/impl/lazy_list.h +++ b/cds/container/impl/lazy_list.h @@ -157,20 +157,18 @@ namespace cds { namespace container { /// Guarded pointer typedef typename gc::template guarded_ptr< node_type, value_type, details::guarded_ptr_cast_set > guarded_ptr; - private: + protected: //@cond static value_type& node_to_value( node_type& n ) { return n.m_Value; } + static value_type const& node_to_value( node_type const& n ) { return n.m_Value; } - //@endcond - protected: - //@cond template static node_type * alloc_node( Q const& v ) { @@ -756,6 +754,11 @@ namespace cds { namespace container { protected: //@cond + bool insert_node( node_type * pNode ) + { + return insert_node_at( head(), pNode ); + } + bool insert_node_at( head_type& refHead, node_type * pNode ) { assert( pNode != nullptr ); diff --git a/cds/container/lazy_list_nogc.h b/cds/container/lazy_list_nogc.h index 2ffe636c..469159d6 100644 --- a/cds/container/lazy_list_nogc.h +++ b/cds/container/lazy_list_nogc.h @@ -96,6 +96,11 @@ namespace cds { namespace container { protected: //@cond + static value_type& node_to_value( node_type& n ) + { + return n.m_Value; + } + static node_type * alloc_node() { return cxx_allocator().New(); @@ -441,6 +446,11 @@ namespace cds { namespace container { protected: //@cond + 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 ); diff --git a/cds/container/lazy_list_rcu.h b/cds/container/lazy_list_rcu.h index 2d08ef03..b900a7a2 100644 --- a/cds/container/lazy_list_rcu.h +++ b/cds/container/lazy_list_rcu.h @@ -161,20 +161,18 @@ namespace cds { namespace container { /// Type of \p get() member function return value typedef value_type * raw_ptr; - private: + protected: //@cond static value_type& node_to_value( node_type& n ) { return n.m_Value; } + static value_type const& node_to_value( node_type const& n ) { return n.m_Value; } - //@endcond - protected: - //@cond template static node_type * alloc_node( Q const& v ) { @@ -772,6 +770,11 @@ namespace cds { namespace container { protected: //@cond + bool insert_node( node_type * pNode ) + { + return insert_node_at( head(), pNode ); + } + bool insert_node_at( head_type& refHead, node_type * pNode ) { assert( pNode != nullptr ); -- 2.34.1