From 140998db06d5e9726986fe578e60773b88216005 Mon Sep 17 00:00:00 2001 From: khizmax Date: Thu, 21 Apr 2016 23:31:53 +0300 Subject: [PATCH] Fixed emplace() --- cds/container/bronson_avltree_map_rcu.h | 46 ++++++++----------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/cds/container/bronson_avltree_map_rcu.h b/cds/container/bronson_avltree_map_rcu.h index 723fb109..2d24efa1 100644 --- a/cds/container/bronson_avltree_map_rcu.h +++ b/cds/container/bronson_avltree_map_rcu.h @@ -263,7 +263,7 @@ namespace cds { namespace container { ) == update_flags::result_inserted; } - /// For key \p key inserts data of type \p mapped_type created in-place from \p args + /// For \p key inserts data of type \p mapped_type created in-place from \p args /** Returns \p true if inserting successful, \p false otherwise. @@ -272,36 +272,20 @@ namespace cds { namespace container { template bool emplace( K&& key, Args&&... args ) { -# if !( CDS_COMPILER == CDS_COMPILER_GCC && CDS_COMPILER_VERSION >= 40800 && CDS_COMPILER_VERSION < 40900 ) - // Probably, the following code is not so efficient, since we pass lvalues instead rvalues to lambda - //TODO: study how to pass a parameter pack to a lambda efficiently using perfect forwarding - // see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#904 - this is what we need - return base_class::do_update( key, key_comparator(), - [&args...]( node_type * pNode ) -> mapped_type * - { - assert( pNode->m_pValue.load( memory_model::memory_order_relaxed ) == nullptr ); - CDS_UNUSED( pNode ); - return cxx_allocator().New( std::forward(args)...); - }, - update_flags::allow_insert - ) == update_flags::result_inserted; -# else - // gcc 4.8 error: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226 - // workaround (from http://stackoverflow.com/questions/14191989/how-do-i-use-variadic-perfect-forwarding-into-a-lambda) - auto f = std::bind( - []( Args... args) -> mapped_type* { return cxx_allocator().New( std::move(args)...); }, - std::forward(args)... - ); - return base_class::do_update( key, key_comparator(), - [&f]( node_type * pNode ) -> mapped_type * - { - assert( pNode->m_pValue.load( memory_model::memory_order_relaxed ) == nullptr ); - CDS_UNUSED( pNode ); - return f(); - }, - update_flags::allow_insert - ) == update_flags::result_inserted; -# endif + struct scoped_ptr + { + mapped_type * pVal; + scoped_ptr( mapped_type * p ): pVal( p ) {} + ~scoped_ptr() { if ( pVal ) cxx_allocator().Delete( pVal ); } + void release() { pVal = nullptr; } + }; + + scoped_ptr p( cxx_allocator().MoveNew( std::forward( args )... )); + if ( base_class::insert( std::forward( key ), p.pVal )) { + p.release(); + return true; + } + return false; } /// Updates the value for \p key -- 2.34.1