using exempt_ptr = cds::urcu::exempt_ptr< gc, node_type, value_type, typename maker::intrusive_traits::disposer,
cds::urcu::details::conventional_exempt_pair_cast<node_type, value_type>
>;
+ /// Type of \p get() member function return value
+ typedef value_type * get_result;
protected:
//@cond
public:
using exempt_ptr = cds::urcu::exempt_ptr< gc, node_type, value_type, typename maker::intrusive_traits::disposer >; ///< pointer to extracted node
+ /// Type of \p get() member function return value
+ typedef value_type * get_result;
private:
//@cond
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;
+ /// Type of \p get() member function return value
+ typedef raw_ptr get_result;
protected:
//@cond
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;
+ /// Type of \p get() member function return value
+ typedef raw_ptr get_result;
private:
//@cond
typedef typename bucket_type::exempt_ptr exempt_ptr; ///< pointer to extracted node
/// Group of \p extract_xxx functions require external locking if underlying ordered list requires that
static CDS_CONSTEXPR const bool c_bExtractLockExternal = bucket_type::c_bExtractLockExternal;
+ /// Type of \p get() member function return value
+ typedef typename bucket_type::get_result get_result;
//@cond
typedef cds::container::michael_map::implementation_tag implementation_tag;
unlinks it from the map, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found.
If the item is not found the function return an empty \p exempt_ptr.
- @note The function does NOT call RCU read-side lock or synchronization,
- and does NOT dispose the item found. It just excludes the item from the map
- and returns a pointer to item found.
- You should lock RCU before calling of the function, and you should synchronize RCU
- outside the RCU lock to free extracted item
+ The function just excludes the key from the map and returns a pointer to item found.
+ Depends on \p bucket_type you should or should not lock RCU before calling of this function:
+ - for the set based on \ref cds_nonintrusive_MichaelList_rcu "MichaelList" RCU should not be locked
+ - for the set based on \ref cds_nonintrusive_LazyList_rcu "LazyList" RCU should be locked
+ See ordered list implementation for details.
\code
#include <cds/urcu/general_buffered.h>
// ...
rcu_michael_map::exempt_ptr p;
- {
- // first, we should lock RCU
- rcu_michael_map::rcu_lock lock;
-
- // Now, you can apply extract function
- // Note that you must not delete the item found inside the RCU lock
- p = theMap.extract( 10 );
- if ( p ) {
- // do something with p
- ...
- }
+
+ // For MichaelList we should not lock RCU
+
+ // Note that you must not delete the item found inside the RCU lock
+ p = theMap.extract( 10 );
+ if ( p ) {
+ // do something with p
+ ...
}
// We may safely release p here
The function returns \p true if \p key is found, \p false otherwise.
*/
template <typename K, typename Func>
- bool find( K const& key, Func f ) const
+ bool find( K const& key, Func f )
{
return bucket( key ).find( key, f );
}
\p Less must imply the same element order as the comparator used for building the map.
*/
template <typename K, typename Less, typename Func>
- bool find_with( K const& key, Less pred, Func f ) const
+ bool find_with( K const& key, Less pred, Func f )
{
return bucket( key ).find_with( key, pred, f );
}
The function applies RCU lock internally.
*/
template <typename K>
- bool find( K const& key ) const
+ bool find( K const& key )
{
return bucket( key ).find( key );
}
\p Less must imply the same element order as the comparator used for building the map.
*/
template <typename K, typename Less>
- bool find_with( K const& key, Less pred ) const
+ bool find_with( K const& key, Less pred )
{
return bucket( key ).find_with( key, pred );
}
/** \anchor cds_nonintrusive_MichaelHashMap_rcu_get
The function searches the item with key equal to \p key and returns the pointer to item found.
If \p key is not found it returns \p nullptr.
+ Note the type of returned value depends on underlying \p bucket_type.
+ For details, see documentation of ordered list you use.
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::MichaelHashMap< your_template_parameters > hash_map;
hash_map theMap;
// ...
+ typename hash_map::get_result gp;
{
// Lock RCU
hash_map::rcu_lock lock;
- hash_map::value_type * = theMap.get( 5 );
- if ( pVal ) {
- // Deal with pVal
+ gp = theMap.get( 5 );
+ if ( gp ) {
+ // Deal with gp
//...
}
// Unlock RCU by rcu_lock destructor
- // pVal can be freed at any time after RCU has been unlocked
+ // gp can be reclaimed at any time after RCU has been unlocked
}
\endcode
*/
template <typename K>
- value_type * get( K const& key ) const
+ get_result get( K const& key )
{
return bucket( key ).get( key );
}
\p pred must imply the same element order as the comparator used for building the map.
*/
template <typename K, typename Less>
- value_type * get_with( K const& key, Less pred ) const
+ get_result get_with( K const& key, Less pred )
{
return bucket( key ).get_with( key, pred );
}
typedef typename bucket_type::rcu_lock rcu_lock; ///< RCU scoped lock
typedef typename bucket_type::exempt_ptr exempt_ptr; ///< pointer to extracted node
+ typedef typename bucket_type::get_result get_result; ///< Return type of \p get() member function and its derivatives
/// Group of \p extract_xxx functions require external locking if underlying ordered list requires that
static CDS_CONSTEXPR const bool c_bExtractLockExternal = bucket_type::c_bExtractLockExternal;
unlinks it from the set, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found.
If the item with the key equal to \p key is not found the function return an empty \p exempt_ptr.
- @note The function does NOT call RCU read-side lock or synchronization,
- and does NOT dispose the item found. It just excludes the item from the set
- and returns a pointer to item found.
- You should lock RCU before calling of the function, and you should synchronize RCU
- outside the RCU lock to free extracted item
+ The function just excludes the item from the set and returns a pointer to item found.
+ Depends on \p bucket_type you should or should not lock RCU before calling of this function:
+ - for the set based on \ref cds_nonintrusive_MichaelList_rcu "MichaelList" RCU should not be locked
+ - for the set based on \ref cds_nonintrusive_LazyList_rcu "LazyList" RCU should be locked
+ See ordered list implementation for details.
\code
#include <cds/urcu/general_buffered.h>
rcu_michael_set theSet;
// ...
- rcu_michael_set::exempt_ptr p;
- {
- // first, we should lock RCU
- rcu_michael_set::rcu_lock lock;
-
- // Now, you can apply extract function
- // Note that you must not delete the item found inside the RCU lock
- p = theSet.extract( 10 );
- if ( p ) {
- // do something with p
- ...
- }
+ typename rcu_michael_set::exempt_ptr p;
+
+ // For MichaelList we should not lock RCU
+
+ // Note that you must not delete the item found inside the RCU lock
+ p = theSet.extract( 10 );
+ if ( p ) {
+ // do something with p
+ ...
}
// We may safely release p here
The function returns \p true if \p key is found, \p false otherwise.
*/
template <typename Q, typename Func>
- bool find( Q& key, Func f ) const
+ bool find( Q& key, Func f )
{
return bucket( key ).find( key, f );
}
//@cond
template <typename Q, typename Func>
- bool find( Q const& key, Func f ) const
+ bool find( Q const& key, Func f )
{
return bucket( key ).find( key, f );
}
\p Less must imply the same element order as the comparator used for building the set.
*/
template <typename Q, typename Less, typename Func>
- bool find_with( Q& key, Less pred, Func f ) const
+ bool find_with( Q& key, Less pred, Func f )
{
return bucket( key ).find_with( key, pred, f );
}
//@cond
template <typename Q, typename Less, typename Func>
- bool find_with( Q const& key, Less pred, Func f ) const
+ bool find_with( Q const& key, Less pred, Func f )
{
return bucket( key ).find_with( key, pred, f );
}
should accept a parameter of type \p Q that may be not the same as \p value_type.
*/
template <typename Q>
- bool find( Q const & key ) const
+ bool find( Q const & key )
{
return bucket( key ).find( key );
}
\p Less must imply the same element order as the comparator used for building the set.
*/
template <typename Q, typename Less>
- bool find_with( Q const & key, Less pred ) const
+ bool find_with( Q const & key, Less pred )
{
return bucket( key ).find_with( key, pred );
}
/** \anchor cds_nonintrusive_MichaelHashSet_rcu_get
The function searches the item with key equal to \p key and returns the pointer to item found.
If \p key is not found it returns \p nullptr.
+ Note the type of returned value depends on underlying \p bucket_type.
+ For details, see documentation of ordered list you use.
Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type.
\code
typedef cds::container::MichaelHashSet< your_template_parameters > hash_set;
hash_set theSet;
+ typename hash_set::get_result gp;
// ...
{
// Lock RCU
hash_set::rcu_lock lock;
- foo * pVal = theSet.get( 5 );
- if ( pVal ) {
+ gp = theSet.get( 5 );
+ if ( gp ) {
// Deal with pVal
//...
}
// Unlock RCU by rcu_lock destructor
- // pVal can be freed at any time after RCU has been unlocked
+ // gp can be reclaimed at any time after RCU has been unlocked
}
\endcode
*/
template <typename Q>
- value_type * get( Q const& key ) const
+ get_result get( Q const& key )
{
return bucket( key ).get( key );
}
\p pred must imply the same element order as the comparator used for building the set.
*/
template <typename Q, typename Less>
- value_type * get_with( Q const& key, Less pred ) const
+ get_result get_with( Q const& key, Less pred )
{
return bucket( key ).get_with( key, pred );
}
public:
/// pointer to extracted node
using exempt_ptr = cds::urcu::exempt_ptr< gc, value_type, value_type, clear_and_dispose, void >;
+ /// Type of \p get() member function return value
+ typedef value_type * get_result;
protected:
//@cond
public:
/// Result of \p get(), \p get_with() functions - pointer to the node found
- typedef cds::urcu::raw_ptr< gc, value_type, raw_ptr_disposer > raw_ptr;
+ typedef cds::urcu::raw_ptr< gc, value_type, raw_ptr_disposer > raw_ptr;
+ /// Type of \p get() member function return value
+ typedef raw_ptr get_result;
protected:
//@cond
typedef typename bucket_type::rcu_lock rcu_lock; ///< RCU scoped lock
typedef typename bucket_type::exempt_ptr exempt_ptr; ///< pointer to extracted node
+ typedef typename bucket_type::get_result get_result; ///< Return type of \p get() member function and its derivatives
/// Group of \p extract_xxx functions require external locking if underlying ordered list requires that
static CDS_CONSTEXPR const bool c_bExtractLockExternal = bucket_type::c_bExtractLockExternal;
unlinks it from the set, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found.
If the item with the key equal to \p key is not found the function returns an empty \p exempt_ptr.
- @note The function does NOT call RCU read-side lock or synchronization,
- and does NOT dispose the item found. It just excludes the item from the set
- and returns a pointer to item found.
- You should lock RCU before calling of the function, and you should synchronize RCU
- outside the RCU lock before reusing returned pointer.
+ Depends on \p bucket_type you should or should not lock RCU before calling of this function:
+ - for the set based on \ref cds_intrusive_MichaelList_rcu "MichaelList" RCU should not be locked
+ - for the set based on \ref cds_intrusive_LazyList_rcu "LazyList" RCU should be locked
+ See ordered list implementation for details.
\code
#include <cds/urcu/general_buffered.h>
// ...
typename rcu_michael_set::exempt_ptr p;
- {
- // first, we should lock RCU
- typename rcu_michael_set::rcu_lock lock;
-
- // Now, you can apply extract function
- // Note that you must not delete the item found inside the RCU lock
- p = theSet.extract( 10 )
- if ( p ) {
- // do something with p
- ...
- }
+
+ // For MichaelList we should not lock RCU
+
+ // Now, you can apply extract function
+ // Note that you must not delete the item found inside the RCU lock
+ p = theSet.extract( 10 )
+ if ( p ) {
+ // do something with p
+ ...
}
// We may safely release p here
and returns \p true if \p key found or \p false otherwise.
*/
template <typename Q>
- bool find( Q const& key ) const
+ bool find( Q const& key )
{
return bucket( key ).find( key );
}
\p pred must imply the same element order as the comparator used for building the set.
*/
template <typename Q, typename Less>
- bool find_with( Q const& key, Less pred ) const
+ bool find_with( Q const& key, Less pred )
{
return bucket( key ).find_with( key, pred );
}
The function returns \p true if \p key is found, \p false otherwise.
*/
template <typename Q, typename Func>
- bool find( Q& key, Func f ) const
+ bool find( Q& key, Func f )
{
return bucket( key ).find( key, f );
}
//@cond
template <typename Q, typename Func>
- bool find( Q const& key, Func f ) const
+ bool find( Q const& key, Func f )
{
return bucket( key ).find( key, f );
}
\p pred must imply the same element order as the comparator used for building the set.
*/
template <typename Q, typename Less, typename Func>
- bool find_with( Q& key, Less pred, Func f ) const
+ bool find_with( Q& key, Less pred, Func f )
{
return bucket( key ).find_with( key, pred, f );
}
//@cond
template <typename Q, typename Less, typename Func>
- bool find_with( Q const& key, Less pred, Func f ) const
+ bool find_with( Q const& key, Less pred, Func f )
{
return bucket( key ).find_with( key, pred, f );
}
/** \anchor cds_intrusive_MichaelHashSet_rcu_get
The function searches the item with key equal to \p key and returns the pointer to item found.
If \p key is not found it returns \p nullptr.
+ Note the type of returned value depends on underlying \p bucket_type.
+ For details, see documentation of ordered list you use.
Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type.
typedef cds::intrusive::MichaelHashSet< your_template_parameters > hash_set;
hash_set theSet;
// ...
+ // Result of get() call
+ typename hash_set::get_result ptr;
{
// Lock RCU
hash_set::rcu_lock lock;
- foo * pVal = theSet.get( 5 );
- if ( pVal ) {
- // Deal with pVal
+ ptr = theSet.get( 5 );
+ if ( ptr ) {
+ // Deal with ptr
//...
}
// Unlock RCU by rcu_lock destructor
- // pVal can be retired by disposer at any time after RCU has been unlocked
+ // ptr can be reclaimed by disposer at any time after RCU has been unlocked
}
\endcode
*/
template <typename Q>
- value_type * get( Q const& key ) const
+ get_result get( Q const& key )
{
return bucket( key ).get( key );
}
\p pred must imply the same element order as the comparator used for building the set.
*/
template <typename Q, typename Less>
- value_type * get_with( Q const& key, Less pred ) const
+ get_result get_with( Q const& key, Less pred )
{
return bucket( key ).get_with( key, pred );
}
test_iter<Map>();
}
+ template <class Map>
+ void test_rcu_michael_list()
+ {
+ Map m( 52, 4 );
+
+ test_int_with(m);
+
+ // extract/get test
+ {
+ typedef typename Map::gc rcu;
+ typedef typename Map::rcu_lock rcu_lock;
+ typedef typename Map::value_type value_type;
+ typename Map::exempt_ptr ep;
+ typename Map::get_result gp;
+
+ static size_t const nLimit = 100;
+ int arr[nLimit];
+ for ( size_t i = 0; i < nLimit; ++i )
+ arr[i] = (int) i;
+ shuffle( arr, arr + nLimit );
+
+ for ( size_t i = 0; i < nLimit; ++i )
+ CPPUNIT_ASSERT( m.insert( arr[i], arr[i] ));
+
+ for ( size_t i = 0; i < nLimit; i += 2 ) {
+ int nKey = arr[i];
+ {
+ rcu_lock l;
+ gp = m.get( nKey );
+ CPPUNIT_ASSERT( gp );
+ CPPUNIT_CHECK( gp->first == nKey );
+ CPPUNIT_CHECK( gp->second.m_val == nKey );
+ }
+ gp.release();
+
+ ep = m.extract( nKey );
+ CPPUNIT_ASSERT( ep );
+ CPPUNIT_ASSERT( !ep.empty() );
+ CPPUNIT_CHECK( nKey == ep->first );
+ CPPUNIT_CHECK( nKey == ep->second.m_val );
+ ep.release();
+
+ {
+ rcu_lock l;
+ CPPUNIT_CHECK( !m.get( nKey ));
+ }
+ ep = m.extract( nKey );
+ CPPUNIT_CHECK( !ep );
+ CPPUNIT_CHECK( ep.empty() );
+
+ {
+ rcu_lock l;
+ nKey = arr[i+1];
+ gp = m.get_with( other_item(nKey), other_less() );
+ CPPUNIT_ASSERT( gp );
+ CPPUNIT_CHECK( gp->first == nKey );
+ CPPUNIT_CHECK( gp->second.m_val == nKey );
+ }
+ gp.release();
+
+ ep = m.extract_with( other_item( nKey ), other_less() );
+ CPPUNIT_ASSERT( ep );
+ CPPUNIT_ASSERT( !ep.empty() );
+ CPPUNIT_CHECK( nKey == ep->first );
+ CPPUNIT_CHECK( nKey == (*ep).second.m_val );
+ ep.release();
+
+ {
+ rcu_lock l;
+ CPPUNIT_CHECK( !m.get_with( other_item(nKey), other_less() ));
+ }
+ CPPUNIT_CHECK( !m.extract_with( other_item(nKey), other_less() ));
+ CPPUNIT_CHECK( ep.empty() );
+ }
+ CPPUNIT_CHECK( m.empty() );
+ CPPUNIT_CHECK( check_size( m, 0 ));
+ {
+ rcu_lock l;
+ CPPUNIT_CHECK( !m.get( int(nLimit / 2) ));
+ }
+ ep = m.extract( int( nLimit / 2 ) );
+ CPPUNIT_CHECK( !ep );
+ CPPUNIT_CHECK( ep.empty() );
+ }
+
+ // iterator test
+ test_iter<Map>();
+ }
+
template <class Map>
void test_int_with( Map& m )
{
// traits-based version
typedef cc::MichaelHashMap< rcu_type, list, map_traits > map;
- test_rcu< map >();
+ test_rcu_michael_list< map >();
// option-based version
typedef cc::MichaelHashMap< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_map;
- test_rcu< opt_map >();
+ test_rcu_michael_list< opt_map >();
}
void HashMapHdrTest::Michael_RCU_GPB_less()
// traits-based version
typedef cc::MichaelHashMap< rcu_type, list, map_traits > map;
- test_rcu< map >();
+ test_rcu_michael_list< map >();
// option-based version
typedef cc::MichaelHashMap< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_map;
- test_rcu< opt_map >();
+ test_rcu_michael_list< opt_map >();
}
void HashMapHdrTest::Michael_RCU_GPB_cmpmix()
// traits-based version
typedef cc::MichaelHashMap< rcu_type, list, map_traits > map;
- test_rcu< map >();
+ test_rcu_michael_list< map >();
// option-based version
typedef cc::MichaelHashMap< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_map;
- test_rcu< opt_map >();
+ test_rcu_michael_list< opt_map >();
}
// traits-based version
typedef cc::MichaelHashMap< rcu_type, list, map_traits > map;
- test_rcu< map >();
+ test_rcu_michael_list< map >();
// option-based version
typedef cc::MichaelHashMap< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_map;
- test_rcu< opt_map >();
+ test_rcu_michael_list< opt_map >();
}
void HashMapHdrTest::Michael_RCU_GPI_less()
// traits-based version
typedef cc::MichaelHashMap< rcu_type, list, map_traits > map;
- test_rcu< map >();
+ test_rcu_michael_list< map >();
// option-based version
typedef cc::MichaelHashMap< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_map;
- test_rcu< opt_map >();
+ test_rcu_michael_list< opt_map >();
}
void HashMapHdrTest::Michael_RCU_GPI_cmpmix()
// traits-based version
typedef cc::MichaelHashMap< rcu_type, list, map_traits > map;
- test_rcu< map >();
+ test_rcu_michael_list< map >();
// option-based version
typedef cc::MichaelHashMap< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_map;
- test_rcu< opt_map >();
+ test_rcu_michael_list< opt_map >();
}
// traits-based version
typedef cc::MichaelHashMap< rcu_type, list, map_traits > map;
- test_rcu< map >();
+ test_rcu_michael_list< map >();
// option-based version
typedef cc::MichaelHashMap< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_map;
- test_rcu< opt_map >();
+ test_rcu_michael_list< opt_map >();
}
void HashMapHdrTest::Michael_RCU_GPT_less()
// traits-based version
typedef cc::MichaelHashMap< rcu_type, list, map_traits > map;
- test_rcu< map >();
+ test_rcu_michael_list< map >();
// option-based version
typedef cc::MichaelHashMap< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_map;
- test_rcu< opt_map >();
+ test_rcu_michael_list< opt_map >();
}
void HashMapHdrTest::Michael_RCU_GPT_cmpmix()
// traits-based version
typedef cc::MichaelHashMap< rcu_type, list, map_traits > map;
- test_rcu< map >();
+ test_rcu_michael_list< map >();
// option-based version
typedef cc::MichaelHashMap< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_map;
- test_rcu< opt_map >();
+ test_rcu_michael_list< opt_map >();
}
// traits-based version
typedef cc::MichaelHashMap< rcu_type, list, map_traits > map;
- test_rcu< map >();
+ test_rcu_michael_list< map >();
// option-based version
typedef cc::MichaelHashMap< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_map;
- test_rcu< opt_map >();
+ test_rcu_michael_list< opt_map >();
#endif
}
// traits-based version
typedef cc::MichaelHashMap< rcu_type, list, map_traits > map;
- test_rcu< map >();
+ test_rcu_michael_list< map >();
// option-based version
typedef cc::MichaelHashMap< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_map;
- test_rcu< opt_map >();
+ test_rcu_michael_list< opt_map >();
#endif
}
// traits-based version
typedef cc::MichaelHashMap< rcu_type, list, map_traits > map;
- test_rcu< map >();
+ test_rcu_michael_list< map >();
// option-based version
typedef cc::MichaelHashMap< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_map;
- test_rcu< opt_map >();
+ test_rcu_michael_list< opt_map >();
#endif
}
// traits-based version
typedef cc::MichaelHashMap< rcu_type, list, map_traits > map;
- test_rcu< map >();
+ test_rcu_michael_list< map >();
// option-based version
typedef cc::MichaelHashMap< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_map;
- test_rcu< opt_map >();
+ test_rcu_michael_list< opt_map >();
#endif
}
// traits-based version
typedef cc::MichaelHashMap< rcu_type, list, map_traits > map;
- test_rcu< map >();
+ test_rcu_michael_list< map >();
// option-based version
typedef cc::MichaelHashMap< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_map;
- test_rcu< opt_map >();
+ test_rcu_michael_list< opt_map >();
#endif
}
// traits-based version
typedef cc::MichaelHashMap< rcu_type, list, map_traits > map;
- test_rcu< map >();
+ test_rcu_michael_list< map >();
// option-based version
typedef cc::MichaelHashMap< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_map;
- test_rcu< opt_map >();
+ test_rcu_michael_list< opt_map >();
#endif
}
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
void IntrusiveHashSetHdrTest::RCU_GPB_base_less()
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
void IntrusiveHashSetHdrTest::RCU_GPB_base_cmpmix()
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
void IntrusiveHashSetHdrTest::RCU_GPB_member_cmp()
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
void IntrusiveHashSetHdrTest::RCU_GPB_member_less()
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
void IntrusiveHashSetHdrTest::RCU_GPB_member_cmpmix()
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
};
typedef ci::MichaelHashSet< RCU, bucket_type, set_traits > set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
void IntrusiveHashSetHdrTest::RCU_GPI_base_less()
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
void IntrusiveHashSetHdrTest::RCU_GPI_base_cmpmix()
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
void IntrusiveHashSetHdrTest::RCU_GPI_member_cmp()
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
void IntrusiveHashSetHdrTest::RCU_GPI_member_less()
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
void IntrusiveHashSetHdrTest::RCU_GPI_member_cmpmix()
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
void IntrusiveHashSetHdrTest::RCU_GPT_base_less()
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
void IntrusiveHashSetHdrTest::RCU_GPT_base_cmpmix()
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
void IntrusiveHashSetHdrTest::RCU_GPT_member_cmp()
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
void IntrusiveHashSetHdrTest::RCU_GPT_member_less()
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
void IntrusiveHashSetHdrTest::RCU_GPT_member_cmpmix()
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
}
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
#endif
}
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
#endif
}
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
#endif
}
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
#endif
}
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
#endif
}
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
#endif
}
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
#endif
}
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
#endif
}
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
#endif
}
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
#endif
}
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
#endif
}
>::type
> set;
- test_rcu_int<set>();
+ test_rcu_int_michael_list<set>();
#endif
}
CPPUNIT_ASSERT( s.insert( arrItems[i] ));
for ( size_t i = 0; i < nLimit; i += 2 ) {
- value_type * pVal;
+ value_type * 1;
int nKey = arr[i];
{
rcu_lock l;
}
}
+ template <class Set>
+ void test_rcu_int_michael_list()
+ {
+ {
+ Set s( 64, 4 );
+ test_rcu_int_with( s );
+ }
+
+ // Iterator test
+ test_iter<Set>();
+
+ // Extract tests
+ typedef typename Set::gc rcu;
+ typedef typename Set::value_type value_type;
+ typedef typename Set::rcu_lock rcu_lock;
+
+ typename Set::exempt_ptr ep;
+ typename Set::get_result gp;
+
+ {
+ static size_t const nLimit = 1024;
+ value_type arrItems[nLimit];
+ int arr[nLimit];
+ for ( size_t i = 0; i < nLimit; ++i )
+ arr[i] = (int) i;
+ shuffle( arr, arr + nLimit );
+
+ for ( size_t i = 0; i < nLimit; ++i ) {
+ arrItems[i].nKey = arr[i];
+ arrItems[i].nVal = arr[i] * 2;
+ }
+
+ Set s( nLimit, 2 );
+ for ( size_t i = 0; i < nLimit; ++i )
+ CPPUNIT_ASSERT( s.insert( arrItems[i] ));
+
+ for ( size_t i = 0; i < nLimit; i += 2 ) {
+ int nKey = arr[i];
+ {
+ rcu_lock l;
+ gp = s.get( nKey );
+ CPPUNIT_ASSERT( gp );
+ CPPUNIT_CHECK( gp->nKey == nKey );
+ CPPUNIT_CHECK( (*gp).nVal == nKey * 2 );
+ }
+ gp.release();
+
+ ep = s.extract( nKey );
+ CPPUNIT_ASSERT( ep );
+ CPPUNIT_ASSERT( !ep.empty() );
+ CPPUNIT_CHECK( nKey == ep->nKey );
+ CPPUNIT_CHECK( nKey * 2 == (*ep).nVal );
+ ep.release();
+ {
+ rcu_lock l;
+ CPPUNIT_CHECK( !s.get( nKey ));
+ }
+ CPPUNIT_CHECK( !s.extract( nKey ));
+ CPPUNIT_CHECK( ep.empty() );
+
+ nKey = arr[i+1];
+ {
+ rcu_lock l;
+ gp = s.get_with( nKey, less<value_type>() );
+ CPPUNIT_ASSERT( gp );
+ CPPUNIT_CHECK( gp->nKey == nKey );
+ CPPUNIT_CHECK( gp->nVal == nKey * 2 );
+ }
+ gp.release();
+
+ ep = s.extract_with( nKey, less<value_type>() );
+ CPPUNIT_ASSERT( ep );
+ CPPUNIT_ASSERT( !ep.empty() );
+ CPPUNIT_CHECK( nKey == ep->nKey );
+ CPPUNIT_CHECK( nKey * 2 == (*ep).nVal );
+ ep.release();
+
+ {
+ rcu_lock l;
+ CPPUNIT_CHECK( !s.get_with( nKey, less<value_type>()));
+ }
+ ep = s.extract_with( nKey, less<value_type>() );
+ CPPUNIT_CHECK( !ep );
+ CPPUNIT_CHECK( ep.empty() );
+ }
+ CPPUNIT_CHECK( s.empty() );
+ CPPUNIT_CHECK( check_size( s, 0 ));
+ {
+ rcu_lock l;
+ CPPUNIT_CHECK( !s.get( 100 ));
+ }
+ ep = s.extract( 100 );
+ CPPUNIT_CHECK( !ep );
+ CPPUNIT_CHECK( ep.empty() );
+
+ Set::gc::force_dispose();
+ }
+ }
+
// MichaelHashSet + MichaelList
void HP_base_cmp();
void HP_base_less();
// traits-based version
typedef cc::MichaelHashSet< rcu_type, list, set_traits > set;
- test_int_rcu< set >();
+ test_int_rcu_michael_list< set >();
// option-based version
typedef cc::MichaelHashSet< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_set;
- test_int_rcu< opt_set >();
+ test_int_rcu_michael_list< opt_set >();
}
void HashSetHdrTest::Michael_RCU_GPB_less()
// traits-based version
typedef cc::MichaelHashSet< rcu_type, list, set_traits > set;
- test_int_rcu< set >();
+ test_int_rcu_michael_list< set >();
// option-based version
typedef cc::MichaelHashSet< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_set;
- test_int_rcu< opt_set >();
+ test_int_rcu_michael_list< opt_set >();
}
void HashSetHdrTest::Michael_RCU_GPB_cmpmix()
// traits-based version
typedef cc::MichaelHashSet< rcu_type, list, set_traits > set;
- test_int_rcu< set >();
+ test_int_rcu_michael_list< set >();
// option-based version
typedef cc::MichaelHashSet< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_set;
- test_int_rcu< opt_set >();
+ test_int_rcu_michael_list< opt_set >();
}
// traits-based version
typedef cc::MichaelHashSet< rcu_type, list, set_traits > set;
- test_int_rcu< set >();
+ test_int_rcu_michael_list< set >();
// option-based version
typedef cc::MichaelHashSet< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_set;
- test_int_rcu< opt_set >();
+ test_int_rcu_michael_list< opt_set >();
}
void HashSetHdrTest::Michael_RCU_GPI_less()
// traits-based version
typedef cc::MichaelHashSet< rcu_type, list, set_traits > set;
- test_int_rcu< set >();
+ test_int_rcu_michael_list< set >();
// option-based version
typedef cc::MichaelHashSet< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_set;
- test_int_rcu< opt_set >();
+ test_int_rcu_michael_list< opt_set >();
}
void HashSetHdrTest::Michael_RCU_GPI_cmpmix()
// traits-based version
typedef cc::MichaelHashSet< rcu_type, list, set_traits > set;
- test_int_rcu< set >();
+ test_int_rcu_michael_list< set >();
// option-based version
typedef cc::MichaelHashSet< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_set;
- test_int_rcu< opt_set >();
+ test_int_rcu_michael_list< opt_set >();
}
// traits-based version
typedef cc::MichaelHashSet< rcu_type, list, set_traits > set;
- test_int_rcu< set >();
+ test_int_rcu_michael_list< set >();
// option-based version
typedef cc::MichaelHashSet< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_set;
- test_int_rcu< opt_set >();
+ test_int_rcu_michael_list< opt_set >();
}
void HashSetHdrTest::Michael_RCU_GPT_less()
// traits-based version
typedef cc::MichaelHashSet< rcu_type, list, set_traits > set;
- test_int_rcu< set >();
+ test_int_rcu_michael_list< set >();
// option-based version
typedef cc::MichaelHashSet< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_set;
- test_int_rcu< opt_set >();
+ test_int_rcu_michael_list< opt_set >();
}
void HashSetHdrTest::Michael_RCU_GPT_cmpmix()
// traits-based version
typedef cc::MichaelHashSet< rcu_type, list, set_traits > set;
- test_int_rcu< set >();
+ test_int_rcu_michael_list< set >();
// option-based version
typedef cc::MichaelHashSet< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_set;
- test_int_rcu< opt_set >();
+ test_int_rcu_michael_list< opt_set >();
}
// traits-based version
typedef cc::MichaelHashSet< rcu_type, list, set_traits > set;
- test_int_rcu< set >();
+ test_int_rcu_michael_list< set >();
// option-based version
typedef cc::MichaelHashSet< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_set;
- test_int_rcu< opt_set >();
+ test_int_rcu_michael_list< opt_set >();
#endif
}
// traits-based version
typedef cc::MichaelHashSet< rcu_type, list, set_traits > set;
- test_int_rcu< set >();
+ test_int_rcu_michael_list< set >();
// option-based version
typedef cc::MichaelHashSet< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_set;
- test_int_rcu< opt_set >();
+ test_int_rcu_michael_list< opt_set >();
#endif
}
// traits-based version
typedef cc::MichaelHashSet< rcu_type, list, set_traits > set;
- test_int_rcu< set >();
+ test_int_rcu_michael_list< set >();
// option-based version
typedef cc::MichaelHashSet< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_set;
- test_int_rcu< opt_set >();
+ test_int_rcu_michael_list< opt_set >();
#endif
}
// traits-based version
typedef cc::MichaelHashSet< rcu_type, list, set_traits > set;
- test_int_rcu< set >();
+ test_int_rcu_michael_list< set >();
// option-based version
typedef cc::MichaelHashSet< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_set;
- test_int_rcu< opt_set >();
+ test_int_rcu_michael_list< opt_set >();
#endif
}
// traits-based version
typedef cc::MichaelHashSet< rcu_type, list, set_traits > set;
- test_int_rcu< set >();
+ test_int_rcu_michael_list< set >();
// option-based version
typedef cc::MichaelHashSet< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_set;
- test_int_rcu< opt_set >();
+ test_int_rcu_michael_list< opt_set >();
#endif
}
// traits-based version
typedef cc::MichaelHashSet< rcu_type, list, set_traits > set;
- test_int_rcu< set >();
+ test_int_rcu_michael_list< set >();
// option-based version
typedef cc::MichaelHashSet< rcu_type, list,
,cc::opt::item_counter< simple_item_counter >
>::type
> opt_set;
- test_int_rcu< opt_set >();
+ test_int_rcu_michael_list< opt_set >();
#endif
}
test_iter<Set>();
}
+ template <class Set>
+ void test_int_rcu_michael_list()
+ {
+ Set s( 100, 4 );
+ test_int_with( s );
+
+ // extract/get test
+ {
+ typedef typename Set::gc rcu;
+ typedef typename Set::rcu_lock rcu_lock;
+ typedef typename Set::value_type value_type;
+ typename Set::exempt_ptr ep;
+ typename Set::get_result gp;
+
+ static size_t const nLimit = 100;
+ int arr[nLimit];
+ for ( size_t i = 0; i < nLimit; ++i )
+ arr[i] = (int) i;
+ shuffle( arr, arr + nLimit );
+
+ for ( size_t i = 0; i < nLimit; ++i )
+ CPPUNIT_ASSERT( s.insert( arr[i] ));
+
+ for ( size_t i = 0; i < nLimit; i += 2 ) {
+ int nKey = arr[i];
+ {
+ rcu_lock l;
+ gp = s.get( nKey );
+ CPPUNIT_ASSERT( gp );
+ CPPUNIT_CHECK( gp->nKey == nKey );
+ CPPUNIT_CHECK( gp->nVal == nKey );
+ }
+ gp.release();
+
+ ep = s.extract( nKey );
+ CPPUNIT_ASSERT( ep );
+ CPPUNIT_ASSERT( !ep.empty() );
+ CPPUNIT_CHECK( nKey == ep->nKey );
+ CPPUNIT_CHECK( nKey == (*ep).nVal );
+ ep.release();
+
+ {
+ rcu_lock l;
+ CPPUNIT_CHECK( !s.get( nKey ));
+ }
+ ep = s.extract( nKey );
+ CPPUNIT_CHECK( !ep );
+ CPPUNIT_CHECK( ep.empty() );
+
+ {
+ rcu_lock l;
+ nKey = arr[i+1];
+ gp = s.get_with( other_item(nKey), other_less() );
+ CPPUNIT_ASSERT( gp );
+ CPPUNIT_CHECK( gp->nKey == nKey );
+ CPPUNIT_CHECK( gp->nVal == nKey );
+ }
+ gp.release();
+
+ ep = s.extract_with( other_item( nKey ), other_less() );
+ CPPUNIT_ASSERT( ep );
+ CPPUNIT_ASSERT( !ep.empty() );
+ CPPUNIT_CHECK( nKey == ep->nKey );
+ CPPUNIT_CHECK( nKey == (*ep).nVal );
+ ep.release();
+
+ {
+ rcu_lock l;
+ CPPUNIT_CHECK( !s.get_with( other_item( nKey ), other_less()));
+ }
+ CPPUNIT_CHECK( !s.extract_with( other_item(nKey), other_less() ));
+ CPPUNIT_CHECK( ep.empty() );
+ }
+ CPPUNIT_CHECK( s.empty() );
+ CPPUNIT_CHECK( check_size( s, 0 ));
+
+ {
+ rcu_lock l;
+ CPPUNIT_CHECK( !s.get( int( nLimit / 2 )));
+ }
+
+ ep = s.extract( int( nLimit / 2 ) );
+ CPPUNIT_CHECK( !ep );
+ CPPUNIT_CHECK( ep.empty() );
+ }
+
+ // iterator test
+ test_iter<Set>();
+ }
+
+
template <class Set>
void test_int_with( Set& s)
{