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