Changed: use padding option instead of alignment one
[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         struct queue_traits : public cds::intrusive::fcqueue::traits
172         {
173             typedef TestIntrusiveFCQueue::disposer disposer;
174             typedef cds::intrusive::fcqueue::stat<> stat;
175         };
176         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type >, queue_traits > 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         struct queue_traits : public
185             cds::intrusive::fcqueue::make_traits <
186                 cds::intrusive::opt::disposer< disposer >
187                 ,cds::opt::enable_elimination < true >
188             > ::type
189         {};
190         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type >, queue_traits > queue_type;
191
192         test<queue_type>();
193     }
194
195     void TestIntrusiveFCQueue::FCQueue_base_elimination_mutex()
196     {
197         typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
198         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type >,
199             cds::intrusive::fcqueue::make_traits<
200                 cds::intrusive::opt::disposer< disposer >
201                 ,cds::opt::enable_elimination< true >
202                 ,cds::opt::lock_type< std::mutex >
203             >::type
204         > queue_type;
205
206         test<queue_type>();
207     }
208
209     void TestIntrusiveFCQueue::FCQueue_base_seqcst()
210     {
211         typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
212         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type >,
213             cds::intrusive::fcqueue::make_traits<
214                 cds::intrusive::opt::disposer< disposer >
215                 ,cds::opt::memory_model< cds::opt::v::sequential_consistent >
216             >::type
217         > queue_type;
218
219         test<queue_type>();
220     }
221
222     void TestIntrusiveFCQueue::FCQueue_member()
223     {
224         typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
225         typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
226
227         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type, member_option >,
228             cds::intrusive::fcqueue::make_traits<
229                 cds::intrusive::opt::disposer< disposer >
230             >::type
231         > queue_type;
232
233         test<queue_type>();
234     }
235
236     void TestIntrusiveFCQueue::FCQueue_member_stat()
237     {
238         typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
239         typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
240
241         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type, member_option >,
242             cds::intrusive::fcqueue::make_traits<
243                 cds::intrusive::opt::disposer< disposer >
244                 ,cds::opt::stat< cds::intrusive::fcqueue::stat<> >
245             >::type
246         > queue_type;
247
248         test<queue_type>();
249     }
250
251     void TestIntrusiveFCQueue::FCQueue_member_elimination()
252     {
253         typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
254         typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
255
256         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type, member_option >,
257             cds::intrusive::fcqueue::make_traits<
258                 cds::intrusive::opt::disposer< disposer >
259                 ,cds::opt::enable_elimination< true >
260             >::type
261         > queue_type;
262
263         test<queue_type>();
264     }
265
266     void TestIntrusiveFCQueue::FCQueue_member_elimination_mutex()
267     {
268         typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
269         typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
270
271         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type, member_option >,
272             cds::intrusive::fcqueue::make_traits<
273                 cds::intrusive::opt::disposer< disposer >
274                 ,cds::opt::enable_elimination< true >
275                 ,cds::opt::lock_type< std::mutex >
276             >::type
277         > queue_type;
278
279         test<queue_type>();
280     }
281
282     void TestIntrusiveFCQueue::FCQueue_member_seqcst()
283     {
284         typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
285         typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
286
287         typedef cds::intrusive::FCQueue< value_type, boost::intrusive::list< value_type, member_option >,
288             cds::intrusive::fcqueue::make_traits<
289                 cds::intrusive::opt::disposer< disposer >
290                 ,cds::opt::memory_model< cds::opt::v::sequential_consistent >
291             >::type
292         > queue_type;
293
294         test<queue_type>();
295     }
296
297 } // namespace queue
298
299 CPPUNIT_TEST_SUITE_REGISTRATION(queue::TestIntrusiveFCQueue);