Removed redundant spaces
[libcds.git] / test / unit / stack / intrusive_fcstack.cpp
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 #include <gtest/gtest.h>
32 #include <cds/intrusive/fcstack.h>
33
34 #include <boost/intrusive/list.hpp>
35
36 namespace {
37     class IntrusiveFCStack : public ::testing::Test
38     {
39     protected:
40         template <typename Hook>
41         struct base_hook_item : public Hook
42         {
43             int nVal;
44             int nDisposeCount;
45
46             base_hook_item()
47                 : nDisposeCount( 0 )
48             {}
49         };
50
51         template <typename Hook>
52         struct member_hook_item
53         {
54             int nVal;
55             int nDisposeCount;
56             Hook hMember;
57
58             member_hook_item()
59                 : nDisposeCount( 0 )
60             {}
61         };
62
63         struct mock_disposer
64         {
65             template <typename T>
66             void operator ()( T * p )
67             {
68                 ++p->nDisposeCount;
69             }
70         };
71
72         template <class Stack>
73         void test()
74         {
75             typedef typename Stack::value_type  value_type;
76             Stack stack;
77
78             ASSERT_TRUE( stack.empty());
79
80             value_type v1, v2, v3;
81             v1.nVal = 1;
82             v2.nVal = 2;
83             v3.nVal = 3;
84             ASSERT_TRUE( stack.push( v1 ));
85             ASSERT_TRUE( !stack.empty());
86             ASSERT_TRUE( stack.push( v2 ));
87             ASSERT_TRUE( !stack.empty());
88             ASSERT_TRUE( stack.push( v3 ));
89             ASSERT_TRUE( !stack.empty());
90
91             value_type * pv;
92             pv = stack.pop();
93             ASSERT_TRUE( pv != nullptr );
94             ASSERT_EQ( pv->nVal, 3 );
95             ASSERT_TRUE( !stack.empty());
96             pv = stack.pop();
97             ASSERT_TRUE( pv != nullptr );
98             ASSERT_EQ( pv->nVal, 2 );
99             ASSERT_TRUE( !stack.empty());
100             pv = stack.pop();
101             ASSERT_TRUE( pv != nullptr );
102             ASSERT_EQ( pv->nVal, 1 );
103             ASSERT_TRUE( stack.empty());
104             pv = stack.pop();
105             ASSERT_TRUE( pv == nullptr );
106             ASSERT_TRUE( stack.empty());
107
108             if ( !std::is_same<typename Stack::disposer, cds::intrusive::opt::v::empty_disposer>::value ) {
109                 int v1disp = v1.nDisposeCount;
110                 int v2disp = v2.nDisposeCount;
111                 int v3disp = v3.nDisposeCount;
112
113                 ASSERT_TRUE( stack.push( v1 ));
114                 ASSERT_TRUE( stack.push( v2 ));
115                 ASSERT_TRUE( stack.push( v3 ));
116
117                 stack.clear();
118                 ASSERT_TRUE( stack.empty());
119
120                 EXPECT_EQ( v1.nDisposeCount, v1disp);
121                 EXPECT_EQ( v2.nDisposeCount, v2disp);
122                 EXPECT_EQ( v3.nDisposeCount, v3disp);
123
124                 ASSERT_TRUE( stack.push( v1 ));
125                 ASSERT_TRUE( stack.push( v2 ));
126                 ASSERT_TRUE( stack.push( v3 ));
127                 ASSERT_TRUE( !stack.empty());
128
129                 stack.clear( true );
130                 ASSERT_TRUE( stack.empty());
131
132                 EXPECT_EQ( v1.nDisposeCount, v1disp + 1 );
133                 EXPECT_EQ( v2.nDisposeCount, v2disp + 1 );
134                 EXPECT_EQ( v3.nDisposeCount, v3disp + 1 );
135             }
136         }
137     };
138
139     TEST_F( IntrusiveFCStack, slist )
140     {
141         typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
142         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type > > stack_type;
143         test<stack_type>();
144     }
145
146     TEST_F( IntrusiveFCStack, slist_empty_wait_strategy )
147     {
148         typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
149         struct stack_traits: public cds::intrusive::fcstack::traits
150         {
151             typedef cds::algo::flat_combining::wait_strategy::empty wait_strategy;
152         };
153         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
154         test<stack_type>();
155     }
156
157     TEST_F( IntrusiveFCStack, slist_single_mutex_single_condvar )
158     {
159         typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
160         struct stack_traits: public cds::intrusive::fcstack::traits
161         {
162             typedef cds::algo::flat_combining::wait_strategy::single_mutex_single_condvar<> wait_strategy;
163         };
164         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
165         test<stack_type>();
166     }
167
168     TEST_F( IntrusiveFCStack, slist_single_mutex_multi_condvar )
169     {
170         typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
171         struct stack_traits: public cds::intrusive::fcstack::traits
172         {
173             typedef cds::algo::flat_combining::wait_strategy::single_mutex_multi_condvar<> wait_strategy;
174         };
175         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
176         test<stack_type>();
177     }
178
179     TEST_F( IntrusiveFCStack, slist_multi_mutex_multi_condvar )
180     {
181         typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
182         struct stack_traits: public cds::intrusive::fcstack::traits
183         {
184             typedef cds::algo::flat_combining::wait_strategy::multi_mutex_multi_condvar<> wait_strategy;
185         };
186         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
187         test<stack_type>();
188     }
189
190     TEST_F( IntrusiveFCStack, slist_single_mutex_single_condvar_2ms )
191     {
192         typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
193         struct stack_traits: public cds::intrusive::fcstack::traits
194         {
195             typedef cds::algo::flat_combining::wait_strategy::single_mutex_single_condvar<2> wait_strategy;
196         };
197         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
198         test<stack_type>();
199     }
200
201     TEST_F( IntrusiveFCStack, slist_single_mutex_multi_condvar_3ms )
202     {
203         typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
204         struct stack_traits: public cds::intrusive::fcstack::traits
205         {
206             typedef cds::algo::flat_combining::wait_strategy::single_mutex_multi_condvar<3> wait_strategy;
207         };
208         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
209         test<stack_type>();
210     }
211
212     TEST_F( IntrusiveFCStack, slist_multi_mutex_multi_condvar_2ms )
213     {
214         typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
215         struct stack_traits: public cds::intrusive::fcstack::traits
216         {
217             typedef cds::algo::flat_combining::wait_strategy::multi_mutex_multi_condvar<2> wait_strategy;
218         };
219         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
220         test<stack_type>();
221     }
222
223     TEST_F( IntrusiveFCStack, slist_disposer )
224     {
225         typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
226         struct stack_traits : public cds::intrusive::fcstack::traits
227         {
228             typedef mock_disposer disposer;
229         };
230         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
231         test<stack_type>();
232     }
233
234     TEST_F( IntrusiveFCStack, slist_mutex )
235     {
236         typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
237         struct stack_traits : public cds::intrusive::fcstack::traits
238         {
239             typedef std::mutex lock_type;
240         };
241         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
242         test<stack_type>();
243     }
244
245     TEST_F( IntrusiveFCStack, slist_elimination )
246     {
247         typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
248         struct stack_traits : public
249             cds::intrusive::fcstack::make_traits <
250             cds::opt::enable_elimination < true >
251             > ::type
252         {};
253         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
254         test<stack_type>();
255     }
256
257     TEST_F( IntrusiveFCStack, slist_elimination_disposer )
258     {
259         typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
260         struct stack_traits : public
261             cds::intrusive::fcstack::make_traits <
262                 cds::opt::enable_elimination < true >,
263                 cds::intrusive::opt::disposer< mock_disposer >,
264                 cds::opt::wait_strategy< cds::algo::flat_combining::wait_strategy::multi_mutex_multi_condvar<>>
265             > ::type
266         {};
267         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >, stack_traits > stack_type;
268         test<stack_type>();
269     }
270
271     TEST_F( IntrusiveFCStack, slist_elimination_stat )
272     {
273         typedef base_hook_item< boost::intrusive::slist_base_hook<> > value_type;
274         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type >,
275             cds::intrusive::fcstack::make_traits<
276                 cds::opt::enable_elimination< true >
277                 , cds::opt::stat< cds::intrusive::fcstack::stat<> >
278                 , cds::opt::wait_strategy< cds::algo::flat_combining::wait_strategy::single_mutex_multi_condvar<>>
279             >::type
280         > stack_type;
281         test<stack_type>();
282     }
283
284     TEST_F( IntrusiveFCStack, slist_member )
285     {
286         typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
287         typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
288
289         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type, member_option > > stack_type;
290         test<stack_type>();
291     }
292
293     TEST_F( IntrusiveFCStack, slist_member_empty_wait_strategy )
294     {
295         typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
296         typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
297         struct stack_traits: public cds::intrusive::fcstack::traits
298         {
299             typedef cds::algo::flat_combining::wait_strategy::empty wait_strategy;
300         };
301
302         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type, member_option >, stack_traits > stack_type;
303         test<stack_type>();
304     }
305
306     TEST_F( IntrusiveFCStack, slist_member_single_mutex_single_condvar )
307     {
308         typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
309         typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
310         struct stack_traits: public cds::intrusive::fcstack::traits
311         {
312             typedef cds::algo::flat_combining::wait_strategy::single_mutex_single_condvar<> wait_strategy;
313         };
314
315         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type, member_option >, stack_traits > stack_type;
316         test<stack_type>();
317     }
318
319     TEST_F( IntrusiveFCStack, slist_member_single_mutex_multi_condvar )
320     {
321         typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
322         typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
323         struct stack_traits: public cds::intrusive::fcstack::traits
324         {
325             typedef cds::algo::flat_combining::wait_strategy::single_mutex_multi_condvar<> wait_strategy;
326         };
327
328         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type, member_option >, stack_traits > stack_type;
329         test<stack_type>();
330     }
331
332     TEST_F( IntrusiveFCStack, slist_member_multi_mutex_multi_condvar )
333     {
334         typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
335         typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
336         struct stack_traits: public cds::intrusive::fcstack::traits
337         {
338             typedef cds::algo::flat_combining::wait_strategy::multi_mutex_multi_condvar<> wait_strategy;
339         };
340
341         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type, member_option >, stack_traits > stack_type;
342         test<stack_type>();
343     }
344
345     TEST_F( IntrusiveFCStack, slist_member_disposer )
346     {
347         typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
348         typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
349         struct stack_traits : public cds::intrusive::fcstack::traits
350         {
351             typedef mock_disposer disposer;
352         };
353
354         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type, member_option >, stack_traits > stack_type;
355         test<stack_type>();
356     }
357
358     TEST_F( IntrusiveFCStack, slist_member_elimination )
359     {
360         typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
361         typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
362
363         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type, member_option >,
364             cds::intrusive::fcstack::make_traits<
365             cds::opt::enable_elimination< true >
366             >::type
367         > stack_type;
368         test<stack_type>();
369     }
370
371     TEST_F( IntrusiveFCStack, slist_member_elimination_stat )
372     {
373         typedef member_hook_item< boost::intrusive::slist_member_hook<> > value_type;
374         typedef boost::intrusive::member_hook<value_type, boost::intrusive::slist_member_hook<>, &value_type::hMember> member_option;
375
376         typedef cds::intrusive::FCStack< value_type, boost::intrusive::slist< value_type, member_option >,
377             cds::intrusive::fcstack::make_traits<
378             cds::opt::enable_elimination< true >
379             , cds::opt::stat< cds::intrusive::fcstack::stat<> >
380             , cds::opt::wait_strategy< cds::algo::flat_combining::wait_strategy::single_mutex_multi_condvar<>>
381             >::type
382         > stack_type;
383         test<stack_type>();
384     }
385
386     TEST_F( IntrusiveFCStack, list )
387     {
388         typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
389         typedef cds::intrusive::FCStack< value_type, boost::intrusive::list< value_type > > stack_type;
390         test<stack_type>();
391     }
392
393     TEST_F( IntrusiveFCStack, list_mutex )
394     {
395         typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
396         typedef cds::intrusive::FCStack< value_type, boost::intrusive::list< value_type >,
397             cds::intrusive::fcstack::make_traits<
398             cds::opt::lock_type< std::mutex >
399             >::type
400         > stack_type;
401         test<stack_type>();
402     }
403
404
405     TEST_F( IntrusiveFCStack, list_elimination )
406     {
407         typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
408         typedef cds::intrusive::FCStack< value_type, boost::intrusive::list< value_type >,
409             cds::intrusive::fcstack::make_traits<
410             cds::opt::enable_elimination< true >
411             >::type
412         > stack_type;
413         test<stack_type>();
414     }
415
416     TEST_F( IntrusiveFCStack, list_elimination_stat )
417     {
418         typedef base_hook_item< boost::intrusive::list_base_hook<> > value_type;
419         typedef cds::intrusive::FCStack< value_type, boost::intrusive::list< value_type >,
420             cds::intrusive::fcstack::make_traits<
421             cds::opt::enable_elimination< true >
422             , cds::opt::stat< cds::intrusive::fcstack::stat<> >
423             , cds::opt::wait_strategy< cds::algo::flat_combining::wait_strategy::multi_mutex_multi_condvar<>>
424             >::type
425         > stack_type;
426         test<stack_type>();
427     }
428
429     TEST_F( IntrusiveFCStack, list_member )
430     {
431         typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
432         typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
433
434         typedef cds::intrusive::FCStack< value_type, boost::intrusive::list< value_type, member_option > > stack_type;
435         test<stack_type>();
436     }
437
438     TEST_F( IntrusiveFCStack, list_member_elimination )
439     {
440         typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
441         typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
442
443         typedef cds::intrusive::FCStack< value_type, boost::intrusive::list< value_type, member_option >,
444             cds::intrusive::fcstack::make_traits<
445             cds::opt::enable_elimination< true >
446             >::type
447         > stack_type;
448         test<stack_type>();
449     }
450
451     TEST_F( IntrusiveFCStack, list_member_elimination_stat )
452     {
453         typedef member_hook_item< boost::intrusive::list_member_hook<> > value_type;
454         typedef boost::intrusive::member_hook<value_type, boost::intrusive::list_member_hook<>, &value_type::hMember> member_option;
455
456         typedef cds::intrusive::FCStack< value_type, boost::intrusive::list< value_type, member_option >,
457             cds::intrusive::fcstack::make_traits<
458             cds::opt::enable_elimination< true >
459             , cds::opt::stat< cds::intrusive::fcstack::stat<> >
460             , cds::opt::wait_strategy< cds::algo::flat_combining::wait_strategy::single_mutex_single_condvar<>>
461             >::type
462         > stack_type;
463         test<stack_type>();
464     }
465
466 } // namespace