#endif
typedef Traits traits; ///< List traits
- typedef typename base_class::back_off back_off; ///< Back-off strategy
- typedef typename maker::allocator_type allocator_type; ///< Allocator type used for allocate/deallocate the nodes
- typedef typename base_class::item_counter item_counter; ///< Item counting policy
- typedef typename maker::key_comparator key_comparator; ///< key comparison functor
- typedef typename base_class::memory_model memory_model; ///< Memory ordering. See \p michael_list::traits::memory_model
+ typedef typename base_class::back_off back_off; ///< Back-off strategy
+ typedef typename maker::allocator_type allocator_type; ///< Allocator type used for allocate/deallocate the nodes
+ typedef typename base_class::item_counter item_counter; ///< Item counting policy
+ typedef typename maker::key_comparator key_comparator; ///< key comparison functor
+ typedef typename base_class::memory_model memory_model; ///< Memory ordering. See \p michael_list::traits::memory_model
typedef typename base_class::rcu_check_deadlock rcu_check_deadlock ; ///< RCU deadlock checking policy
typedef typename gc::scoped_lock rcu_lock ; ///< RCU scoped lock
cds::urcu::details::conventional_exempt_pair_cast<node_type, value_type>
>;
+ private:
+ struct raw_ptr_converter
+ {
+ value_type * operator()( node_type * p ) const
+ {
+ return p ? &p->m_Data : nullptr;
+ }
+
+ value_type& operator()( node_type& n ) const
+ {
+ return n.m_Data;
+ }
+
+ value_type const& operator()( node_type const& n ) const
+ {
+ return n.m_Data;
+ }
+ };
+
+ public:
+ /// Result of \p get(), \p get_with() functions - pointer to the node found
+ typedef cds::urcu::raw_ptr_adaptor< value_type, typename base_class::raw_ptr, raw_ptr_converter > raw_ptr;
+
protected:
//@cond
template <typename K>
In trivial case, \p K is equal to \ref key_type.
- The \ref mapped_type should be default-constructible.
- The function makes RCU lock internally.
+ The function applies RCU lock internally.
Returns \p true if inserting successful, \p false otherwise.
*/
- The \ref key_type should be constructible from \p key of type \p K.
- The \ref mapped_type should be constructible from \p val of type \p V.
- The function makes RCU lock internally.
+ The function applies RCU lock internally.
Returns \p true if inserting successful, \p false otherwise.
*/
This can be useful if complete initialization of object of \p mapped_type is heavyweight and
it is preferable that the initialization should be completed only if inserting is successful.
- The function makes RCU lock internally.
+ The function applies RCU lock internally.
@warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
*/
however, \p func must guarantee that during changing no any other modifications
could be made on this item by concurrent threads.
- The function makes RCU lock internally.
+ The function applies RCU lock internally.
Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
\p second is true if new item has been added or \p false if the item with \p key
/**
Returns \p true if inserting successful, \p false otherwise.
- The function makes RCU lock internally.
+ The function applies RCU lock internally.
*/
template <typename K, typename... Args>
bool emplace( K&& key, Args&&... args )
/// 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 nullptr.
+ If \p key is not found it returns an empty \p raw_ptr object.
Note the compare functor should accept a parameter of type \p K that can be not the same as \p key_type.
typedef cds::container::MichaelKVList< cds::urcu::gc< cds::urcu::general_buffered<> >, int, foo, my_traits > ord_list;
ord_list theList;
// ...
+ tyename ord_list::raw_ptr rp;
{
// Lock RCU
ord_list::rcu_lock lock;
- ord_list::value_type * pVal = theList.get( 5 );
- if ( pVal ) {
- // Deal with pVal
+ rp = theList.get( 5 );
+ if ( rp ) {
+ // Deal with rp
//...
}
// Unlock RCU by rcu_lock destructor
- // pVal can be freed at any time after RCU has been unlocked
}
+ // rp can be released at any time after RCU has been unlocked
+ rp.release();
\endcode
*/
template <typename K>
- value_type * get( K const& key )
+ raw_ptr get( K const& key )
{
return get_at( head(), key, intrusive_key_comparator());
}
\p pred must imply the same element order as the comparator used for building the list.
*/
template <typename K, typename Less>
- value_type * get_with( K const& key, Less pred )
+ raw_ptr get_with( K const& key, Less pred )
{
CDS_UNUSED( pred );
return get_at( head(), key, typename maker::template less_wrapper<Less>::type() );
}
template <typename K, typename Compare>
- value_type * get_at( head_type& refHead, K const& val, Compare cmp )
+ raw_ptr get_at( head_type& refHead, K const& val, Compare cmp )
{
- node_type * pNode = base_class::get_at( refHead, val, cmp );
- return pNode ? &pNode->m_Data : nullptr;
+ return raw_ptr( base_class::get_at( refHead, val, cmp ));
}
//@endcond
CPPUNIT_ASSERT( l.insert( a[i], a[i]*2 ) );
typename OrdList::exempt_ptr ep;
+ typename OrdList::raw_ptr rp;
for ( int i = 0; i < nLimit; ++i ) {
{
rcu_lock lock;
- value_type * pGet = l.get( a[i] );
- CPPUNIT_ASSERT( pGet != nullptr );
- CPPUNIT_CHECK( pGet->first == a[i] );
- CPPUNIT_CHECK( pGet->second.m_val == a[i] * 2 );
-
- ep = l.extract( a[i] );
- CPPUNIT_ASSERT( ep );
- CPPUNIT_ASSERT( !ep.empty() );
- CPPUNIT_CHECK( ep->first == a[i] );
- CPPUNIT_CHECK( (*ep).second.m_val == a[i] * 2 );
+ rp = l.get( a[i] );
+ CPPUNIT_ASSERT( rp );
+ CPPUNIT_CHECK( rp->first == a[i] );
+ CPPUNIT_CHECK( rp->second.m_val == a[i] * 2 );
}
+ rp.release();
+
+ ep = l.extract( a[i] );
+ CPPUNIT_ASSERT( ep );
+ CPPUNIT_ASSERT( !ep.empty() );
+ CPPUNIT_CHECK( ep->first == a[i] );
+ CPPUNIT_CHECK( (*ep).second.m_val == a[i] * 2 );
ep.release();
{
rcu_lock lock;
- CPPUNIT_CHECK( l.get( a[i] ) == nullptr );
- ep = l.extract( a[i] );
- CPPUNIT_CHECK( !ep );
- CPPUNIT_CHECK( ep.empty() );
+ CPPUNIT_CHECK( !l.get( a[i] ));
}
+ ep = l.extract( a[i] );
+ CPPUNIT_CHECK( !ep );
+ CPPUNIT_CHECK( ep.empty() );
}
CPPUNIT_ASSERT( l.empty() );
{
rcu_lock lock;
- CPPUNIT_CHECK( l.get( a[0] ) == nullptr );
- CPPUNIT_CHECK( !l.extract( a[0] ) );
- CPPUNIT_CHECK( ep.empty() );
+ CPPUNIT_CHECK( !l.get( a[0] ));
}
+ CPPUNIT_CHECK( !l.extract( a[0] ) );
+ CPPUNIT_CHECK( ep.empty() );
// extract_with/get_with
for ( int i = 0; i < nLimit; ++i ) {
float itm = a[i] + 0.3f;
{
rcu_lock lock;
- value_type * pGet = l.get_with( itm, other_less() );
- CPPUNIT_ASSERT( pGet != nullptr );
- CPPUNIT_CHECK( pGet->first == a[i] );
- CPPUNIT_CHECK( pGet->second.m_val == a[i] * 2 );
-
- ep = l.extract_with( itm, other_less() );
- CPPUNIT_ASSERT( ep );
- CPPUNIT_ASSERT( !ep.empty() );
- CPPUNIT_CHECK( ep->first == a[i] );
- CPPUNIT_CHECK( ep->second.m_val == a[i] * 2 );
+ rp = l.get_with( itm, other_less() );
+ CPPUNIT_ASSERT( rp );
+ CPPUNIT_CHECK( rp->first == a[i] );
+ CPPUNIT_CHECK( rp->second.m_val == a[i] * 2 );
}
+ rp.release();
+
+ ep = l.extract_with( itm, other_less() );
+ CPPUNIT_ASSERT( ep );
+ CPPUNIT_ASSERT( !ep.empty() );
+ CPPUNIT_CHECK( ep->first == a[i] );
+ CPPUNIT_CHECK( ep->second.m_val == a[i] * 2 );
ep.release();
{
rcu_lock lock;
- CPPUNIT_CHECK( l.get_with( itm, other_less() ) == nullptr );
- ep = l.extract_with( itm, other_less() );
- CPPUNIT_CHECK( !ep );
- CPPUNIT_CHECK( ep.empty() );
+ CPPUNIT_CHECK( !l.get_with( itm, other_less()));
}
+ ep = l.extract_with( itm, other_less() );
+ CPPUNIT_CHECK( !ep );
+ CPPUNIT_CHECK( ep.empty() );
}
CPPUNIT_ASSERT( l.empty() );
{
rcu_lock lock;
- CPPUNIT_CHECK( l.get_with( 3.14f, other_less() ) == nullptr );
- CPPUNIT_CHECK( !l.extract_with( 3.14f, other_less() ));
- CPPUNIT_CHECK( ep.empty() );
+ CPPUNIT_CHECK( !l.get_with( 3.14f, other_less() ));
}
+ CPPUNIT_CHECK( !l.extract_with( 3.14f, other_less() ));
+ CPPUNIT_CHECK( ep.empty() );
}
-
}
template <class OrdList>