) == 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.
template <typename K, typename... Args>
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>(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<mapped_type *>(
- []( Args... args) -> mapped_type* { return cxx_allocator().New( std::move(args)...); },
- std::forward<Args>(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>( args )... ));
+ if ( base_class::insert( std::forward<K>( key ), p.pVal )) {
+ p.release();
+ return true;
+ }
+ return false;
}
/// Updates the value for \p key
RCU \p synchronize() method can be called. RCU should not be locked.
- Returns <tt> std::pair<bool, bool> </tt> where \p first is \p true if operation is successfull,
+ Returns <tt> std::pair<bool, bool> </tt> where \p first is \p true if operation is successful,
\p second is \p true if new item has been added or \p false if the item with \p key
already exists.
*/