Replace NULL with nullptr
[libcds.git] / tests / test-hdr / queue / hdr_intrusive_fcqueue.cpp
1 //$$CDS-header$$
2
3 #include "cppunit/cppunit_proxy.h"
4 #include <cds/intrusive/fcqueue.h>
5
6 namespace queue {
7
8     class TestIntrusiveFCQueue: public CppUnitMini::TestCase
9     {
10         template <typename Hook>
11         struct base_hook_item: public Hook
12         {
13             int nVal;
14             int nDisposeCount;
15
16             base_hook_item()
17                 : nDisposeCount(0)
18             {}
19         };
20
21         template <typename Hook>
22         struct member_hook_item
23         {
24             int nVal;
25             int nDisposeCount;
26             Hook hMember;
27
28             member_hook_item()
29                 : nDisposeCount(0)
30             {}
31         };
32
33         struct disposer
34         {
35             template <typename T>
36             void operator ()( T * p )
37             {
38                 ++p->nDisposeCount;
39             }
40         };
41
42         template <typename Queue>
43         void test()
44         {
45             Queue q;
46             test_with(q);
47         }
48
49         template <class Queue>
50         void test_with( Queue& q )
51         {
52             typedef typename Queue::value_type value_type;
53             value_type v1, v2, v3;
54             CPPUNIT_ASSERT( q.empty() );
55
56             v1.nVal = 1;
57             v2.nVal = 2;
58             v3.nVal = 3;
59             CPPUNIT_ASSERT( q.push(v1));
60             CPPUNIT_ASSERT( !q.empty() );
61             CPPUNIT_ASSERT( q.push(v2));
62             CPPUNIT_ASSERT( !q.empty() );
63             CPPUNIT_ASSERT( q.push(v3));
64             CPPUNIT_ASSERT( !q.empty() );
65
66             CPPUNIT_CHECK( v1.nDisposeCount == 0 );
67             CPPUNIT_CHECK( v2.nDisposeCount == 0 );
68             CPPUNIT_CHECK( v3.nDisposeCount == 0 );
69
70             value_type * pv;
71             pv = q.pop();
72             CPPUNIT_ASSERT( pv != nullptr );
73             CPPUNIT_ASSERT( pv->nVal == 1 );
74             CPPUNIT_ASSERT( !q.empty() );
75             CPPUNIT_CHECK( v1.nDisposeCount == 0 );
76             CPPUNIT_CHECK( v2.nDisposeCount == 0 );
77             CPPUNIT_CHECK( v3.nDisposeCount == 0 );
78
79             pv = q.pop();
80             CPPUNIT_ASSERT( pv != nullptr );
81             CPPUNIT_ASSERT( pv->nVal == 2 );
82             CPPUNIT_ASSERT( !q.empty() );
83             CPPUNIT_CHECK( v1.nDisposeCount == 0 );
84             CPPUNIT_CHECK( v2.nDisposeCount == 0 );
85             CPPUNIT_CHECK( v3.nDisposeCount == 0 );
86
87             pv = q.dequeue();
88             CPPUNIT_ASSERT( pv != nullptr );
89             CPPUNIT_ASSERT( pv->nVal == 3 );
90             CPPUNIT_ASSERT( q.empty() );
91             CPPUNIT_CHECK( v1.nDisposeCount == 0 );
92             CPPUNIT_CHECK( v2.nDisposeCount == 0 );
93             CPPUNIT_CHECK( v3.nDisposeCount == 0 );
94
95             pv = q.dequeue();
96             CPPUNIT_ASSERT( pv == nullptr );
97             CPPUNIT_CHECK( v1.nDisposeCount == 0 );
98             CPPUNIT_CHECK( v2.nDisposeCount == 0 );
99             CPPUNIT_CHECK( v3.nDisposeCount == 0 );
100
101             CPPUNIT_ASSERT( q.enqueue(v1));
102             CPPUNIT_ASSERT( !q.empty() );
103             CPPUNIT_ASSERT( q.enqueue(v2));
104             CPPUNIT_ASSERT( !q.empty() );
105             CPPUNIT_ASSERT( q.enqueue(v3));
106             CPPUNIT_ASSERT( !q.empty() );
107
108             CPPUNIT_CHECK( v1.nDisposeCount == 0 );
109             CPPUNIT_CHECK( v2.nDisposeCount == 0 );
110             CPPUNIT_CHECK( v3.nDisposeCount == 0 );
111             q.clear( true );    // call disposer
112             CPPUNIT_CHECK( q.empty() );
113             CPPUNIT_CHECK( v1.nDisposeCount == 1 );
114             CPPUNIT_CHECK( v2.nDisposeCount == 1 );
115             CPPUNIT_CHECK( v3.nDisposeCount == 1 );
116
117             CPPUNIT_ASSERT( q.push(v1));
118             CPPUNIT_ASSERT( !q.empty() );
119             CPPUNIT_ASSERT( q.push(v2));
120             CPPUNIT_ASSERT( !q.empty() );
121             CPPUNIT_ASSERT( q.push(v3));
122             CPPUNIT_ASSERT( !q.empty() );
123             q.clear( false );   // no disposer called
124             CPPUNIT_CHECK( q.empty() );
125             CPPUNIT_CHECK( v1.nDisposeCount == 1 );
126             CPPUNIT_CHECK( v2.nDisposeCount == 1 );
127             CPPUNIT_CHECK( v3.nDisposeCount == 1 );
128         }
129
130         void FCQueue_base();
131         void FCQueue_base_stat();
132         void FCQueue_base_elimination();
133         void FCQueue_base_elimination_mutex();
134         void FCQueue_base_seqcst();
135         void FCQueue_member();
136         void FCQueue_member_stat();
137         void FCQueue_member_elimination();
138         void FCQueue_member_elimination_mutex();
139         void FCQueue_member_seqcst();
140
141         CPPUNIT_TEST_SUITE(TestIntrusiveFCQueue)
142             CPPUNIT_TEST(FCQueue_base)
143             CPPUNIT_TEST(FCQueue_base_stat)
144             CPPUNIT_TEST(FCQueue_base_elimination)
145             CPPUNIT_TEST(FCQueue_base_elimination_mutex)
146             CPPUNIT_TEST(FCQueue_base_seqcst)
147             CPPUNIT_TEST(FCQueue_member)
148             CPPUNIT_TEST(FCQueue_member_stat)
149             CPPUNIT_TEST(FCQueue_member_elimination)
150             CPPUNIT_TEST(FCQueue_member_elimination_mutex)
151             CPPUNIT_TEST(FCQueue_member_seqcst)
152         CPPUNIT_TEST_SUITE_END()
153     };
154
155
156     void TestIntrusiveFCQueue::FCQueue_base()
157     {
158         typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
159         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type >,
160             cds::intrusive::fcqueue::make_traits<
161                 cds::intrusive::opt::disposer< disposer >
162             >::type
163         > queue_type;
164
165         test<queue_type>();
166     }
167
168     void TestIntrusiveFCQueue::FCQueue_base_stat()
169     {
170         typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
171         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type >,
172             cds::intrusive::fcqueue::make_traits<
173                 cds::intrusive::opt::disposer< disposer >
174                 ,cds::opt::stat< cds::intrusive::fcqueue::stat<> >
175             >::type
176         > queue_type;
177
178         test<queue_type>();
179     }
180
181     void TestIntrusiveFCQueue::FCQueue_base_elimination()
182     {
183         typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
184         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type >,
185             cds::intrusive::fcqueue::make_traits<
186                 cds::intrusive::opt::disposer< disposer >
187                 ,cds::opt::enable_elimination< true >
188             >::type
189         > queue_type;
190
191         test<queue_type>();
192     }
193
194     void TestIntrusiveFCQueue::FCQueue_base_elimination_mutex()
195     {
196         typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
197         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type >,
198             cds::intrusive::fcqueue::make_traits<
199                 cds::intrusive::opt::disposer< disposer >
200                 ,cds::opt::enable_elimination< true >
201                 ,cds::opt::lock_type< std::mutex >
202             >::type
203         > queue_type;
204
205         test<queue_type>();
206     }
207
208     void TestIntrusiveFCQueue::FCQueue_base_seqcst()
209     {
210         typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
211         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type >,
212             cds::intrusive::fcqueue::make_traits<
213                 cds::intrusive::opt::disposer< disposer >
214                 ,cds::opt::memory_model< cds::opt::v::sequential_consistent >
215             >::type
216         > queue_type;
217
218         test<queue_type>();
219     }
220
221     void TestIntrusiveFCQueue::FCQueue_member()
222     {
223         typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
224         typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
225
226         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type, member_option >,
227             cds::intrusive::fcqueue::make_traits<
228                 cds::intrusive::opt::disposer< disposer >
229             >::type
230         > queue_type;
231
232         test<queue_type>();
233     }
234
235     void TestIntrusiveFCQueue::FCQueue_member_stat()
236     {
237         typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
238         typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
239
240         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type, member_option >,
241             cds::intrusive::fcqueue::make_traits<
242                 cds::intrusive::opt::disposer< disposer >
243                 ,cds::opt::stat< cds::intrusive::fcqueue::stat<> >
244             >::type
245         > queue_type;
246
247         test<queue_type>();
248     }
249
250     void TestIntrusiveFCQueue::FCQueue_member_elimination()
251     {
252         typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
253         typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
254
255         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type, member_option >,
256             cds::intrusive::fcqueue::make_traits<
257                 cds::intrusive::opt::disposer< disposer >
258                 ,cds::opt::enable_elimination< true >
259             >::type
260         > queue_type;
261
262         test<queue_type>();
263     }
264
265     void TestIntrusiveFCQueue::FCQueue_member_elimination_mutex()
266     {
267         typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
268         typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
269
270         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type, member_option >,
271             cds::intrusive::fcqueue::make_traits<
272                 cds::intrusive::opt::disposer< disposer >
273                 ,cds::opt::enable_elimination< true >
274                 ,cds::opt::lock_type< std::mutex >
275             >::type
276         > queue_type;
277
278         test<queue_type>();
279     }
280
281     void TestIntrusiveFCQueue::FCQueue_member_seqcst()
282     {
283         typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
284         typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
285
286         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type, member_option >,
287             cds::intrusive::fcqueue::make_traits<
288                 cds::intrusive::opt::disposer< disposer >
289                 ,cds::opt::memory_model< cds::opt::v::sequential_consistent >
290             >::type
291         > queue_type;
292
293         test<queue_type>();
294     }
295
296 } // namespace queue
297
298 CPPUNIT_TEST_SUITE_REGISTRATION(queue::TestIntrusiveFCQueue);