Added internal statistics for LazyList
[libcds.git] / test / unit / list / test_intrusive_list_rcu.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8     
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
15     * Redistributions in binary form must reproduce the above copyright notice,
16       this list of conditions and the following disclaimer in the documentation
17       and/or other materials provided with the distribution.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     
29 */
30 #ifndef CDSUNIT_LIST_TEST_INTRUSIVE_LIST_RCU_H
31 #define CDSUNIT_LIST_TEST_INTRUSIVE_LIST_RCU_H
32
33 #include "test_intrusive_list.h"
34
35 namespace cds_test {
36
37     class intrusive_list_rcu : public intrusive_list_common
38     {
39     protected:
40         template <typename List>
41         void test_rcu( List& l )
42         {
43             // Precondition: list is empty
44             // Postcondition: list is empty
45
46             static const size_t nSize = 20;
47             typedef typename List::value_type value_type;
48             value_type arr[ nSize ];
49
50             for ( size_t i = 0; i < nSize; ++i ) {
51                 arr[i].nKey = static_cast<int>( i );
52                 arr[i].nVal = arr[i].nKey * 10;
53             }
54             shuffle( arr, arr + nSize );
55
56             typedef typename List::exempt_ptr exempt_ptr;
57             typedef typename List::raw_ptr    raw_ptr;
58             typedef typename List::rcu_lock   rcu_lock;
59
60             ASSERT_TRUE( l.empty() );
61             ASSERT_CONTAINER_SIZE( l, 0 );
62
63             // get() test
64             for ( auto& i : arr ) {
65                 {
66                     rcu_lock lock;
67                     raw_ptr rp = l.get( i.nKey );
68                     EXPECT_TRUE( !rp );
69                     rp = l.get_with( other_item( i.nKey ), other_less());
70                     EXPECT_TRUE( !rp );
71                 }
72
73                 EXPECT_TRUE( l.insert( i ));
74
75                 {
76                     rcu_lock lock;
77                     raw_ptr rp = l.get( i.nKey );
78                     ASSERT_FALSE( !rp );
79                     EXPECT_EQ( rp->nKey, i.nKey );
80                     EXPECT_EQ( rp->nVal, i.nVal );
81                 }
82                 {
83                     rcu_lock lock;
84                     raw_ptr rp = l.get_with( other_item( i.nKey ), other_less() );
85                     ASSERT_FALSE( !rp );
86                     EXPECT_EQ( rp->nKey, i.nKey );
87                     EXPECT_EQ( rp->nVal, i.nVal );
88                 }
89             }
90
91             exempt_ptr gp;
92
93             // extract() test
94             if ( List::c_bExtractLockExternal ) {
95                 for ( int i = 0; i < static_cast<int>(nSize); ++i ) {
96                     {
97                         rcu_lock lock;
98
99                         if ( i & 1 )
100                             gp = l.extract( i );
101                         else
102                             gp = l.extract_with( other_item(i), other_less());
103                         ASSERT_FALSE( !gp );
104                         EXPECT_EQ( gp->nKey, i );
105                     }
106                     gp.release();
107                     {
108                         rcu_lock lock;
109
110                         gp = l.extract( i );
111                         EXPECT_TRUE( !gp );
112                         gp = l.extract_with( other_item( i ), other_less() );
113                         EXPECT_TRUE( !gp );
114                     }
115                 }
116             }
117             else {
118                 for ( int i = 0; i < static_cast<int>(nSize); ++i ) {
119                     if ( i & 1 )
120                         gp = l.extract( i );
121                     else
122                         gp = l.extract_with( other_item( i ), other_less() );
123                     ASSERT_FALSE( !gp );
124                     EXPECT_EQ( gp->nKey, i );
125
126                     gp = l.extract( i );
127                     EXPECT_TRUE( !gp );
128                     gp = l.extract_with( other_item( i ), other_less() );
129                     EXPECT_TRUE( !gp );
130                 }
131             }
132
133             ASSERT_TRUE( l.empty() );
134             ASSERT_CONTAINER_SIZE( l, 0 );
135
136             List::gc::force_dispose();
137             for ( auto const& i : arr ) {
138                 EXPECT_EQ( i.s.nDisposeCount, 1 );
139                 EXPECT_FALSE( l.contains( i ) );
140             }
141         }
142     };
143
144 } // namespace cds_test
145
146 #endif // CDSUNIT_LIST_TEST_INTRUSIVE_LIST_RCU_H