From 6f93d275d0d2506ab774e17b16c748bf201069f6 Mon Sep 17 00:00:00 2001 From: Vlad Khorsun Date: Tue, 10 Aug 2021 13:44:02 +0300 Subject: [PATCH] Implement update() with key and value, see issue #170. It allows to insert pre-constructed value if key was not found in list. --- .../cds/container/impl/michael_kvlist.h | 59 +++++++++++++++++-- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/extern/libcds/cds/container/impl/michael_kvlist.h b/extern/libcds/cds/container/impl/michael_kvlist.h index a2e7c5f89e..c7252d8e4b 100644 --- a/extern/libcds/cds/container/impl/michael_kvlist.h +++ b/extern/libcds/cds/container/impl/michael_kvlist.h @@ -470,6 +470,40 @@ namespace cds { namespace container { { return update_at( head(), std::forward( key ), f, bAllowInsert ); } + + /// Updates or inserts data (\p val) by \p key + /** + The operation performs inserting or replacing the element with lock-free manner. + + If the \p key not found in the list, then the \p val will be inserted iff + \p bAllowInsert is \p true. + Otherwise, if \p key is found, the functor \p func is called with item found. + + The functor \p Func signature is: + \code + struct my_functor { + void operator()( bool bNew, value_type& item ); + }; + \endcode + with arguments: + - \p bNew - \p true if the item has been inserted, \p false otherwise + - \p item - the item found or inserted + + The functor may change any fields of the \p item.second of \p mapped_type; + however, \p func must guarantee that during changing no any other modifications + could be made on this item by concurrent threads. + + Returns std::pair where \p first is true if operation is successful, + \p second is true if new item has been added or \p false if the item with \p key + already exists. + + @warning See \ref cds_intrusive_item_creating "insert item troubleshooting" + */ + template + std::pair update( K&& key, V&& val, Func f, bool bAllowInsert = true ) + { + return update_at( head(), std::forward( key ), std::forward( val ), f, bAllowInsert ); + } //@cond template CDS_DEPRECATED("ensure() is deprecated, use update()") @@ -804,20 +838,37 @@ namespace cds { namespace container { return insert_node_at( refHead, alloc_node( std::forward(key), std::forward(args)... )); } - template - std::pair update_at( head_type& refHead, K&& key, Func f, bool bAllowInsert ) + template + std::pair update_node_at( head_type& refHead, node_type* pNode, Func f, bool bAllowInsert ) { - scoped_node_ptr pNode( alloc_node( std::forward( key ))); + scoped_node_ptr p(pNode); std::pair ret = base_class::update_at( refHead, *pNode, [&f]( bool bNew, node_type& node, node_type& ){ f( bNew, node.m_Data ); }, bAllowInsert ); + if ( ret.first && ret.second ) - pNode.release(); + p.release(); return ret; } + template + std::pair update_at( head_type& refHead, K&& key, Func f, bool bAllowInsert ) + { + node_type* pNode = alloc_node( std::forward( key )); + + return update_node_at( refHead, pNode, f, bAllowInsert ); + } + + template + std::pair update_at( head_type& refHead, K&& key, V&& val, Func f, bool bAllowInsert ) + { + node_type* pNode = alloc_node( std::forward( key ), std::forward( val )); + + return update_node_at( refHead, pNode, f, bAllowInsert ); + } + template bool erase_at( head_type& refHead, K const& key, Compare cmp ) {