Added internal statistics for LazyList
[libcds.git] / test / unit / list / test_kv_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
31 #ifndef CDSUNIT_LIST_TEST_KV_LIST_RCU_H
32 #define CDSUNIT_LIST_TEST_KV_LIST_RCU_H
33
34 #include "test_kv_list.h"
35
36 namespace cds_test {
37
38     class kv_list_rcu : public kv_list_common
39     {
40     protected:
41         template <typename List>
42         void test_rcu( List& l )
43         {
44             // Precondition: list is empty
45             // Postcondition: list is empty
46
47             static const size_t nSize = 20;
48             typedef typename List::key_type    list_key_type;
49             typedef typename List::mapped_type list_mapped_type;
50             typedef typename List::value_type  list_value_type;
51             struct key_val {
52                 int key;
53                 int val;
54             };
55             key_val arr[nSize];
56
57             for ( size_t i = 0; i < nSize; ++i ) {
58                 arr[i].key = static_cast<int>(i);
59                 arr[i].val = arr[i].key * 10;
60             }
61             shuffle( arr, arr + nSize );
62
63             ASSERT_TRUE( l.empty() );
64             ASSERT_CONTAINER_SIZE( l, 0 );
65
66             typedef typename List::exempt_ptr exempt_ptr;
67             typedef typename List::raw_ptr    raw_ptr;
68             typedef typename List::rcu_lock   rcu_lock;
69
70             // get() test
71             for ( auto const& i : arr ) {
72                 {
73                     rcu_lock lock;
74                     raw_ptr rp = l.get( i.key );
75                     EXPECT_TRUE( !rp );
76                     rp = l.get_with( other_key( i.key ), other_less() );
77                     EXPECT_TRUE( !rp );
78                 }
79
80                 EXPECT_TRUE( l.insert( i.key, i.val ));
81
82                 {
83                     rcu_lock lock;
84                     raw_ptr rp = l.get( i.key );
85                     ASSERT_FALSE( !rp );
86                     EXPECT_EQ( rp->first.nKey, i.key );
87                     EXPECT_EQ( rp->second.val, i.val );
88                 }
89                 {
90                     rcu_lock lock;
91                     raw_ptr rp = l.get( key_type( i.key ));
92                     ASSERT_FALSE( !rp );
93                     EXPECT_EQ( rp->first.nKey, i.key );
94                     EXPECT_EQ( rp->second.val, i.val );
95                 }
96                 {
97                     rcu_lock lock;
98                     raw_ptr rp = l.get_with( other_key( i.key ), other_less());
99                     ASSERT_FALSE( !rp );
100                     EXPECT_EQ( rp->first.key(), i.key );
101                     EXPECT_EQ( rp->second.val, i.val );
102                 }
103             }
104
105             ASSERT_FALSE( l.empty() );
106             ASSERT_CONTAINER_SIZE( l, nSize );
107
108             // extract()
109
110             exempt_ptr gp;
111             if ( List::c_bExtractLockExternal ) {
112                 for ( auto const& i : arr ) {
113                     {
114                         rcu_lock lock;
115                         if ( i.key & 1 )
116                             gp = l.extract( i.key );
117                         else
118                             gp = l.extract_with( other_key( i.key ), other_less());
119
120                         ASSERT_FALSE( !gp );
121                         EXPECT_EQ( gp->first.key(), i.key );
122                     }
123                     gp.release();
124                     {
125                         rcu_lock lock;
126                         gp = l.extract( i.key );
127                         EXPECT_TRUE( !gp );
128                         gp = l.extract_with( other_key( i.key ), other_less());
129                         EXPECT_TRUE( !gp );
130                     }
131                 }
132             }
133             else {
134                 for ( auto const& i : arr ) {
135                     if ( i.key & 1 )
136                         gp = l.extract( i.key );
137                     else
138                         gp = l.extract_with( other_key( i.key ), other_less());
139
140                     ASSERT_FALSE( !gp );
141                     EXPECT_EQ( gp->first.key(), i.key );
142
143                     gp = l.extract( i.key );
144                     EXPECT_TRUE( !gp );
145                     gp = l.extract_with( other_key( i.key ), other_less());
146                     EXPECT_TRUE( !gp );
147                 }
148             }
149
150             ASSERT_TRUE( l.empty() );
151             ASSERT_CONTAINER_SIZE( l, 0 );
152         }
153     };
154 } // namespace cds_test
155
156 #endif // CDSUNIT_LIST_TEST_KV_LIST_RCU_H