Merge branch 'master' into dev
[libcds.git] / test / unit / queue / vyukov_mpmc_queue.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 "test_bounded_queue.h"
32
33 #include <cds/container/vyukov_mpmc_cycle_queue.h>
34
35 namespace {
36     namespace cc = cds::container;
37
38     class VyukovMPMCCycleQueue: public cds_test::bounded_queue
39     {
40     public:
41         template <typename Queue>
42         void test_single_consumer( Queue& q )
43         {
44             typedef typename Queue::value_type value_type;
45
46             const size_t nSize = q.capacity();
47
48             ASSERT_TRUE( q.empty());
49             ASSERT_CONTAINER_SIZE( q, 0 );
50
51             // enqueue/dequeue
52             for ( unsigned pass = 0; pass < 3; ++pass ) {
53                 for ( size_t i = 0; i < nSize; ++i ) {
54                     ASSERT_TRUE( q.enqueue( static_cast<value_type>( i )) );
55                     ASSERT_CONTAINER_SIZE( q, i + 1 );
56                 }
57                 ASSERT_FALSE( q.empty());
58                 ASSERT_CONTAINER_SIZE( q, nSize );
59                 ASSERT_FALSE( q.enqueue( static_cast<value_type>( nSize ) * 2 ));
60
61                 for ( size_t i = 0; i < nSize; ++i ) {
62                     value_type* fr = q.front();
63                     ASSERT_TRUE( fr != nullptr );
64                     ASSERT_EQ( *fr, static_cast<value_type>( i ));
65                     ASSERT_TRUE( q.pop_front());
66                     ASSERT_CONTAINER_SIZE( q, nSize - i - 1 );
67                 }
68                 ASSERT_TRUE( q.empty());
69                 ASSERT_CONTAINER_SIZE( q, 0 );
70
71                 ASSERT_TRUE( q.front() == nullptr );
72                 ASSERT_FALSE( q.pop_front());
73             }
74         }
75     };
76
77     TEST_F( VyukovMPMCCycleQueue, defaulted )
78     {
79         typedef cds::container::VyukovMPMCCycleQueue< int > test_queue;
80
81         test_queue q( 128 );
82         test(q);
83     }
84
85     TEST_F( VyukovMPMCCycleQueue, stat )
86     {
87         struct traits: public cds::container::vyukov_queue::traits
88         {
89             typedef cds::opt::v::uninitialized_static_buffer<int, 128> buffer;
90         };
91         typedef cds::container::VyukovMPMCCycleQueue< int, traits > test_queue;
92
93         test_queue q;
94         test( q );
95     }
96
97     TEST_F( VyukovMPMCCycleQueue, stat_item_counting )
98     {
99
100         typedef cds::container::VyukovMPMCCycleQueue< int,
101             cds::container::vyukov_queue::make_traits<
102                 cds::opt::buffer< cds::opt::v::uninitialized_static_buffer<int, 128>>
103                 , cds::opt::item_counter< cds::atomicity::item_counter>
104             >::type
105         > test_queue;
106
107         test_queue q;
108         test( q );
109     }
110
111     TEST_F( VyukovMPMCCycleQueue, dynamic )
112     {
113         struct traits : public cds::container::vyukov_queue::traits
114         {
115             typedef cds::opt::v::uninitialized_dynamic_buffer<int> buffer;
116         };
117         typedef cds::container::VyukovMPMCCycleQueue< int, traits > test_queue;
118
119         test_queue q( 128 );
120         test( q );
121     }
122
123     TEST_F( VyukovMPMCCycleQueue, dynamic_item_counting )
124     {
125         typedef cds::container::VyukovMPMCCycleQueue< int,
126             cds::container::vyukov_queue::make_traits<
127                 cds::opt::buffer< cds::opt::v::uninitialized_dynamic_buffer<int>>
128                 , cds::opt::item_counter< cds::atomicity::item_counter>
129             >::type
130         > test_queue;
131
132         test_queue q( 128 );
133         test( q );
134     }
135
136     TEST_F( VyukovMPMCCycleQueue, dynamic_padding )
137     {
138         struct traits : public cds::container::vyukov_queue::traits
139         {
140             typedef cds::opt::v::uninitialized_dynamic_buffer<int> buffer;
141             enum { padding = 64 };
142         };
143         typedef cds::container::VyukovMPMCCycleQueue< int, traits > test_queue;
144
145         test_queue q( 128 );
146         test( q );
147     }
148
149     TEST_F( VyukovMPMCCycleQueue, move )
150     {
151         typedef cds::container::VyukovMPMCCycleQueue< std::string > test_queue;
152
153         test_queue q( 128 );
154         test_string( q );
155     }
156
157     TEST_F( VyukovMPMCCycleQueue, move_item_counting )
158     {
159         struct traits : public cds::container::vyukov_queue::traits
160         {
161             typedef cds::atomicity::item_counter item_counter;
162         };
163         typedef cds::container::VyukovMPMCCycleQueue< std::string, traits > test_queue;
164
165         test_queue q( 128 );
166         test_string( q );
167     }
168
169     TEST_F( VyukovMPMCCycleQueue, single_consumer )
170     {
171         struct traits: public cds::container::vyukov_queue::traits
172         {
173             enum: bool { single_consumer = true };
174         };
175         typedef cds::container::VyukovMPMCCycleQueue< int, traits > test_queue;
176
177         test_queue q( 128 );
178         test( q );
179         test_single_consumer( q );
180     }
181
182 } // namespace
183