tests/test-hdr/ordered_list/hdr_intrusive_michael_list_rcu_shb.cpp \
tests/test-hdr/ordered_list/hdr_intrusive_michael_list_rcu_sht.cpp
+CDS_TESTHDR_OFFSETOF_UNORDLIST := \
+ tests/test-hdr/unordered_list/hdr_intrusive_lazy_nogc.cpp
+
CDS_TESTHDR_OFFSETOF_QUEUE := \
tests/test-hdr/queue/hdr_intrusive_basketqueue_hp.cpp \
tests/test-hdr/queue/hdr_intrusive_basketqueue_dhp.cpp \
$(CDS_TESTHDR_OFFSETOF_MAP) \
$(CDS_TESTHDR_OFFSETOF_SET) \
$(CDS_TESTHDR_OFFSETOF_ORDLIST) \
- $(CDS_TESTHDR_OFFSETOF_TREE)
\ No newline at end of file
+ $(CDS_TESTHDR_OFFSETOF_UNORDLIST) \
+ $(CDS_TESTHDR_OFFSETOF_TREE)
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSTEST_HDR_INTRUSIVE_LAZY_H
+#define CDSTEST_HDR_INTRUSIVE_LAZY_H
+
+#include "cppunit/cppunit_proxy.h"
+#include <cds/intrusive/details/lazy_list_base.h>
+
+namespace unordlist {
+ namespace ci = cds::intrusive;
+ namespace co = cds::opt;
+
+ struct stat {
+ int nDisposeCount;
+ int nEnsureExistsCall;
+ int nEnsureNewCall;
+ int nFindCall;
+ int nEraseCall;
+
+ stat()
+ : nDisposeCount(0)
+ , nEnsureExistsCall(0)
+ , nEnsureNewCall(0)
+ , nFindCall(0)
+ , nEraseCall(0)
+ {}
+
+ stat( const stat& s )
+ {
+ *this = s;
+ }
+
+ stat& operator =(const stat& s)
+ {
+ memcpy( this, &s, sizeof(s));
+ return *this;
+ }
+ };
+
+ template <typename GC>
+ struct base_int_item: public ci::lazy_list::node< GC >
+ {
+ int nKey;
+ int nVal;
+
+ mutable stat s;
+
+ base_int_item()
+ {}
+
+ base_int_item(int key, int val)
+ : nKey( key )
+ , nVal(val)
+ , s()
+ {}
+
+ base_int_item(const base_int_item& v )
+ : nKey( v.nKey )
+ , nVal( v.nVal )
+ , s()
+ {}
+
+ const int& key() const
+ {
+ return nKey;
+ }
+
+ operator int() const
+ { return nKey; }
+ };
+
+ template <typename GC>
+ struct member_int_item
+ {
+ int nKey;
+ int nVal;
+
+ ci::lazy_list::node< GC > hMember;
+
+ mutable stat s;
+
+ member_int_item()
+ {}
+
+ member_int_item(int key, int val)
+ : nKey( key )
+ , nVal(val)
+ , s()
+ {}
+
+ member_int_item(const member_int_item& v )
+ : nKey( v.nKey )
+ , nVal( v.nVal )
+ , s()
+ {}
+
+ const int& key() const
+ {
+ return nKey;
+ }
+
+ operator int() const
+ { return nKey; }
+ };
+
+ template <typename T>
+ struct less
+ {
+ bool operator ()(const T& v1, const T& v2 ) const
+ {
+ return v1.key() < v2.key();
+ }
+
+ template <typename Q>
+ bool operator ()(const T& v1, const Q& v2 ) const
+ {
+ return v1.key() < v2;
+ }
+
+ template <typename Q>
+ bool operator ()(const Q& v1, const T& v2 ) const
+ {
+ return v1 < v2.key();
+ }
+ };
+
+ template <typename T>
+ struct cmp {
+ int operator ()(const T& v1, const T& v2 ) const
+ {
+ if ( v1.key() < v2.key() )
+ return -1;
+ return v1.key() > v2.key() ? 1 : 0;
+ }
+
+ template <typename Q>
+ int operator ()(const T& v1, const Q& v2 ) const
+ {
+ if ( v1.key() < v2 )
+ return -1;
+ return v1.key() > v2 ? 1 : 0;
+ }
+
+ template <typename Q>
+ int operator ()(const Q& v1, const T& v2 ) const
+ {
+ if ( v1 < v2.key() )
+ return -1;
+ return v1 > v2.key() ? 1 : 0;
+ }
+ };
+
+ template <typename T>
+ struct equal_to {
+ bool operator()( T const& l, T const& r ) const
+ {
+ return l.key() == r.key();
+ }
+
+ template <typename Q>
+ bool operator()( Q const& l, T const& r ) const
+ {
+ return l == r.key();
+ }
+
+ template <typename Q>
+ bool operator()( T const& l, Q const& r ) const
+ {
+ return l.key() == r;
+ }
+ };
+
+ struct faked_disposer
+ {
+ template <typename T>
+ void operator ()( T * p )
+ {
+ ++p->s.nDisposeCount;
+ }
+ };
+
+ struct ensure_functor
+ {
+ template <typename T>
+ void operator ()(bool bNew, T& item, T& /*val*/ )
+ {
+ if ( bNew )
+ ++item.s.nEnsureNewCall;
+ else
+ ++item.s.nEnsureExistsCall;
+ }
+ };
+
+ struct find_functor
+ {
+ template <typename T, typename Q>
+ void operator ()( T& item, Q& /*val*/ )
+ {
+ ++item.s.nFindCall;
+ }
+ };
+
+ class UnorderedIntrusiveLazyListHeaderTest: public CppUnitMini::TestCase
+ {
+ public:
+ template <class UnordList>
+ void test_nogc_int()
+ {
+ typedef typename UnordList::value_type value_type;
+ {
+ value_type v1( 10, 50 );
+ value_type v2( 5, 25 );
+ value_type v3( 20, 100 );
+ {
+ UnordList l;
+ CPPUNIT_ASSERT( l.empty() );
+
+ CPPUNIT_ASSERT( l.insert( v1 )); // true
+ CPPUNIT_ASSERT( l.find( v1.key() ) == &v1 );
+
+ CPPUNIT_ASSERT( v1.s.nFindCall == 0 );
+ CPPUNIT_ASSERT( l.find( v1.key(), find_functor() ));
+ CPPUNIT_ASSERT( v1.s.nFindCall == 1 );
+
+ CPPUNIT_ASSERT( l.find( v3.key() ) == nullptr );
+ CPPUNIT_ASSERT( !l.empty() );
+
+ //CPPUNIT_ASSERT( !l.insert( v1 )) ; // assertion "is_empty" is raised
+
+ {
+ value_type v( v1 );
+ CPPUNIT_ASSERT( !l.insert( v )) ; // false
+ }
+
+ std::pair<bool, bool> ret = l.ensure( v2, ensure_functor() );
+ CPPUNIT_ASSERT( ret.first );
+ CPPUNIT_ASSERT( ret.second );
+ CPPUNIT_ASSERT( v2.s.nEnsureNewCall == 1 );
+ CPPUNIT_ASSERT( v2.s.nEnsureExistsCall == 0 );
+
+ //CPPUNIT_ASSERT( !l.insert( v2 )) ; // assertion "is_empty"
+
+ CPPUNIT_ASSERT( l.find( v1.key() ) == &v1 ) ; // true
+
+ CPPUNIT_ASSERT( v1.s.nFindCall == 1 );
+ CPPUNIT_ASSERT( l.find( v1.key(), find_functor() ));
+ CPPUNIT_ASSERT( v1.s.nFindCall == 2 );
+
+ CPPUNIT_ASSERT( !l.find( v3.key() ));
+
+ {
+ value_type v( v2 );
+ ret = l.ensure( v, ensure_functor() );
+
+ CPPUNIT_ASSERT( ret.first );
+ CPPUNIT_ASSERT( !ret.second );
+ CPPUNIT_ASSERT( v2.s.nEnsureExistsCall == 1 );
+ CPPUNIT_ASSERT( v.s.nEnsureExistsCall == 0 && v.s.nEnsureNewCall == 0 );
+ }
+
+ CPPUNIT_ASSERT( !l.empty() );
+
+ CPPUNIT_ASSERT( l.insert( v3 )) ; // true
+ CPPUNIT_ASSERT( l.find( v3.key() ) == &v3 );
+
+ CPPUNIT_ASSERT( v3.s.nFindCall == 0 );
+ CPPUNIT_ASSERT( l.find( v3.key(), find_functor() ));
+ CPPUNIT_ASSERT( v3.s.nFindCall == 1 );
+
+ {
+ typename UnordList::iterator it = l.begin();
+ typename UnordList::const_iterator cit = l.cbegin();
+ CPPUNIT_ASSERT( it != l.end() );
+ CPPUNIT_ASSERT( it != l.cend() );
+ CPPUNIT_ASSERT( cit != l.end() );
+ CPPUNIT_ASSERT( cit != l.cend() );
+ CPPUNIT_ASSERT( cit == it );
+
+ CPPUNIT_ASSERT( it->nKey == v1.nKey );
+ CPPUNIT_ASSERT( it->nVal == v1.nVal );
+ CPPUNIT_ASSERT( ++it != l.end() );
+ CPPUNIT_ASSERT( it->nKey == v2.nKey );
+ CPPUNIT_ASSERT( it->nVal == v2.nVal );
+ CPPUNIT_ASSERT( it++ != l.end() );
+ CPPUNIT_ASSERT( it->nKey == v3.nKey );
+ CPPUNIT_ASSERT( it->nVal == v3.nVal );
+ CPPUNIT_ASSERT( it++ != l.end() );
+ CPPUNIT_ASSERT( it == l.end() );
+ }
+
+ {
+ UnordList const & lref = l;
+ typename UnordList::const_iterator it = lref.begin();
+ CPPUNIT_ASSERT( it != l.end() );
+ CPPUNIT_ASSERT( it->nKey == v1.nKey );
+ CPPUNIT_ASSERT( it->nVal == v1.nVal );
+ CPPUNIT_ASSERT( ++it != lref.end() );
+ CPPUNIT_ASSERT( it->nKey == v2.nKey );
+ CPPUNIT_ASSERT( it->nVal == v2.nVal );
+ CPPUNIT_ASSERT( it++ != l.end() );
+ CPPUNIT_ASSERT( it->nKey == v3.nKey );
+ CPPUNIT_ASSERT( it->nVal == v3.nVal );
+ CPPUNIT_ASSERT( it++ != lref.end() );
+ CPPUNIT_ASSERT( it == l.end() );
+ }
+ }
+
+ // Disposer called on list destruction
+ CPPUNIT_ASSERT( v1.s.nDisposeCount == 1 );
+ CPPUNIT_ASSERT( v2.s.nDisposeCount == 1 );
+ CPPUNIT_ASSERT( v3.s.nDisposeCount == 1 );
+ }
+ }
+
+ void nogc_base_cmp();
+ void nogc_base_less();
+ void nogc_base_equal_to();
+ void nogc_base_cmpmix();
+ void nogc_base_equal_to_mix();
+ void nogc_base_ic();
+ void nogc_member_cmp();
+ void nogc_member_less();
+ void nogc_member_equal_to();
+ void nogc_member_cmpmix();
+ void nogc_member_equal_to_mix();
+ void nogc_member_ic();
+
+ CPPUNIT_TEST_SUITE(UnorderedIntrusiveLazyListHeaderTest)
+
+ CPPUNIT_TEST(nogc_base_cmp)
+ CPPUNIT_TEST(nogc_base_less)
+ CPPUNIT_TEST(nogc_base_equal_to)
+ CPPUNIT_TEST(nogc_base_cmpmix)
+ CPPUNIT_TEST(nogc_base_equal_to_mix)
+ CPPUNIT_TEST(nogc_base_ic)
+ CPPUNIT_TEST(nogc_member_cmp)
+ CPPUNIT_TEST(nogc_member_less)
+ CPPUNIT_TEST(nogc_member_equal_to)
+ CPPUNIT_TEST(nogc_member_cmpmix)
+ CPPUNIT_TEST(nogc_member_equal_to_mix)
+ CPPUNIT_TEST(nogc_member_ic)
+
+ CPPUNIT_TEST_SUITE_END()
+ };
+} // namespace unordlist
+
+#endif // #ifndef CDSTEST_HDR_INTRUSIVE_LAZY_H
--- /dev/null
+//$$CDS-header$$
+
+#include "unordered_list/hdr_intrusive_lazy.h"
+#include <cds/intrusive/lazy_list_nogc.h>
+
+namespace unordlist {
+ namespace {
+ typedef base_int_item< cds::gc::nogc > base_item;
+ typedef member_int_item< cds::gc::nogc > member_item;
+
+ struct cmp_traits : public ci::lazy_list::traits {
+ typedef ci::lazy_list::base_hook< co::gc<cds::gc::nogc> > hook;
+ typedef unordlist::cmp<base_item> compare;
+ typedef faked_disposer disposer;
+ static const bool sort = false;
+ };
+
+ struct less_traits: public ci::lazy_list::traits {
+ typedef ci::lazy_list::base_hook< co::gc<cds::gc::nogc> > hook;
+ typedef unordlist::less<base_item> less;
+ typedef faked_disposer disposer;
+ static const bool sort = false;
+ };
+
+ struct equal_to_traits: public ci::lazy_list::traits {
+ typedef ci::lazy_list::base_hook< co::gc<cds::gc::nogc> > hook;
+ typedef unordlist::equal_to<base_item> equal_to;
+ typedef faked_disposer disposer;
+ static const bool sort = false;
+ };
+
+ typedef typename ci::lazy_list::make_traits<
+ ci::opt::hook< ci::lazy_list::base_hook< co::gc<cds::gc::nogc> > >
+ ,co::less< less<base_item> >
+ ,co::compare< cmp<base_item> >
+ ,ci::opt::disposer< faked_disposer >
+ ,co::sort< false > >::type cmpmix_traits;
+
+ typedef typename ci::lazy_list::make_traits<
+ ci::opt::hook< ci::lazy_list::base_hook< co::gc<cds::gc::nogc> > >
+ ,co::compare< cmp<base_item> >
+ ,co::equal_to< equal_to<base_item> >
+ ,ci::opt::disposer< faked_disposer >
+ ,co::sort< false > >::type equal_to_mix_traits;
+
+ typedef typename ci::lazy_list::make_traits<
+ ci::opt::hook< ci::lazy_list::base_hook< co::gc<cds::gc::nogc> > >
+ ,co::equal_to< equal_to<base_item> >
+ ,ci::opt::disposer< faked_disposer >
+ ,co::item_counter< cds::atomicity::item_counter >
+ ,co::sort< false > >::type ic_traits;
+
+ typedef typename ci::lazy_list::make_traits<
+ ci::opt::hook< ci::lazy_list::member_hook<
+ offsetof( member_item, hMember )
+ ,co::gc<cds::gc::nogc> > >
+ ,co::compare< cmp<member_item> >
+ ,ci::opt::disposer< faked_disposer >
+ ,co::sort< false > >::type member_cmp_traits;
+
+ typedef typename ci::lazy_list::make_traits<
+ ci::opt::hook< ci::lazy_list::member_hook<
+ offsetof( member_item, hMember )
+ ,co::gc<cds::gc::nogc> > >
+ ,co::less< less<member_item> >
+ ,ci::opt::disposer< faked_disposer >
+ ,co::sort< false > >::type member_less_traits;
+
+ typedef typename ci::lazy_list::make_traits<
+ ci::opt::hook< ci::lazy_list::member_hook<
+ offsetof( member_item, hMember )
+ ,co::gc<cds::gc::nogc> > >
+ ,co::equal_to< equal_to<member_item> >
+ ,ci::opt::disposer< faked_disposer >
+ ,co::sort< false > >::type member_equal_to_traits;
+
+ typedef typename ci::lazy_list::make_traits<
+ ci::opt::hook< ci::lazy_list::member_hook<
+ offsetof( member_item, hMember )
+ ,co::gc<cds::gc::nogc> > >
+ ,co::less< less<member_item> >
+ ,co::compare< cmp<member_item> >
+ ,ci::opt::disposer< faked_disposer >
+ ,co::sort< false > >::type member_cmpmix_traits;
+
+ typedef typename ci::lazy_list::make_traits<
+ ci::opt::hook< ci::lazy_list::member_hook<
+ offsetof( member_item, hMember )
+ ,co::gc<cds::gc::nogc> > >
+ ,co::compare< cmp<member_item> >
+ ,co::equal_to< equal_to<member_item> >
+ ,ci::opt::disposer< faked_disposer >
+ ,co::sort< false > >::type member_equal_to_mix_traits;
+
+ typedef typename ci::lazy_list::make_traits<
+ ci::opt::hook< ci::lazy_list::member_hook<
+ offsetof( member_item, hMember ),
+ co::gc<cds::gc::nogc> > >
+ ,co::equal_to< equal_to<member_item> >
+ ,ci::opt::disposer< faked_disposer >
+ ,co::item_counter< cds::atomicity::item_counter >
+ ,co::sort< false > >::type member_ic_traits;
+
+ }
+ void UnorderedIntrusiveLazyListHeaderTest::nogc_base_cmp()
+ {
+ typedef ci::LazyList< cds::gc::nogc, base_item, cmp_traits > list;
+ test_nogc_int<list>();
+ }
+ void UnorderedIntrusiveLazyListHeaderTest::nogc_base_less()
+ {
+ typedef ci::LazyList< cds::gc::nogc, base_item, less_traits > list;
+ test_nogc_int<list>();
+ }
+ void UnorderedIntrusiveLazyListHeaderTest::nogc_base_equal_to()
+ {
+ typedef ci::LazyList< cds::gc::nogc, base_item, equal_to_traits > list;
+ test_nogc_int<list>();
+ }
+ void UnorderedIntrusiveLazyListHeaderTest::nogc_base_cmpmix()
+ {
+ typedef ci::LazyList< cds::gc::nogc, base_item, cmpmix_traits > list;
+ test_nogc_int<list>();
+ }
+ void UnorderedIntrusiveLazyListHeaderTest::nogc_base_equal_to_mix()
+ {
+ typedef ci::LazyList< cds::gc::nogc, base_item, equal_to_mix_traits > list;
+ test_nogc_int<list>();
+ }
+ void UnorderedIntrusiveLazyListHeaderTest::nogc_base_ic()
+ {
+ typedef ci::LazyList< cds::gc::nogc, base_item, ic_traits > list;
+ test_nogc_int<list>();
+ }
+ void UnorderedIntrusiveLazyListHeaderTest::nogc_member_cmp()
+ {
+ typedef ci::LazyList< cds::gc::nogc, member_item, member_cmp_traits > list;
+ test_nogc_int<list>();
+ }
+ void UnorderedIntrusiveLazyListHeaderTest::nogc_member_less()
+ {
+ typedef ci::LazyList< cds::gc::nogc, member_item, member_less_traits > list;
+ test_nogc_int<list>();
+ }
+ void UnorderedIntrusiveLazyListHeaderTest::nogc_member_equal_to()
+ {
+ typedef ci::LazyList< cds::gc::nogc, member_item, member_equal_to_traits > list;
+ test_nogc_int<list>();
+ }
+ void UnorderedIntrusiveLazyListHeaderTest::nogc_member_cmpmix()
+ {
+ typedef ci::LazyList< cds::gc::nogc, member_item, member_cmpmix_traits > list;
+ test_nogc_int<list>();
+ }
+ void UnorderedIntrusiveLazyListHeaderTest::nogc_member_equal_to_mix()
+ {
+ typedef ci::LazyList< cds::gc::nogc, member_item, member_equal_to_mix_traits > list;
+ test_nogc_int<list>();
+ }
+ void UnorderedIntrusiveLazyListHeaderTest::nogc_member_ic()
+ {
+ typedef ci::LazyList< cds::gc::nogc, member_item, member_ic_traits > list;
+ test_nogc_int<list>();
+ }
+
+} // namespace unordlist
+
+CPPUNIT_TEST_SUITE_REGISTRATION(unordlist::UnorderedIntrusiveLazyListHeaderTest);