2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
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.
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.
31 #include "stack_type.h"
32 #include "../misc/common.h"
36 static size_t s_nThreadCount = 8;
37 static size_t s_nStackSize = 10000000;
38 static size_t s_nEliminationSize = 4;
40 class stack_push : public cds_test::stress_fixture
52 value_type( size_t n )
58 template <class Stack>
59 class Producer: public cds_test::thread
61 typedef cds_test::thread base_class;
64 Producer( cds_test::thread_pool& pool, Stack& stack )
72 Producer( Producer& src )
74 , m_stack( src.m_stack )
80 virtual thread * clone()
82 return new Producer( *this );
89 for ( v.nNo = m_nStartItem; v.nNo < m_nEndItem; ++v.nNo ) {
90 if ( !m_stack.push( v ))
103 static void SetUpTestCase()
105 cds_test::config const& cfg = get_config("Stack_Push");
107 s_nThreadCount = cfg.get_size_t( "ThreadCount", s_nThreadCount );
108 s_nStackSize = cfg.get_size_t( "StackSize", s_nStackSize );
109 s_nEliminationSize = cfg.get_size_t( "EliminationSize", s_nEliminationSize );
111 if ( s_nThreadCount == 0 )
115 //static void TearDownTestCase();
117 template <typename Stack>
118 void test( Stack& stack )
120 cds_test::thread_pool& pool = get_pool();
122 pool.add( new Producer<Stack>( pool, stack ), s_nThreadCount );
125 size_t nThreadItemCount = s_nStackSize / s_nThreadCount;
126 for ( size_t i = 0; i < pool.size(); ++i ) {
127 Producer<Stack>& thread = static_cast<Producer<Stack>&>( pool.get( i ));
128 thread.m_nStartItem = nStart;
129 nStart += nThreadItemCount;
130 thread.m_nEndItem = nStart;
133 propout() << std::make_pair( "thread_count", s_nThreadCount )
134 << std::make_pair( "push_count", s_nStackSize );
136 std::chrono::milliseconds duration = pool.run();
138 propout() << std::make_pair( "duration", duration );
140 DEBUG(analyze( stack ));
141 propout() << stack.statistics();
144 template <typename Stack>
145 void test_elimination( Stack& stack )
148 check_elimination_stat( stack.statistics());
151 void check_elimination_stat( cds::container::treiber_stack::empty_stat const& )
154 void check_elimination_stat( cds::container::treiber_stack::stat<> const& s )
156 EXPECT_EQ( s.m_PushCount.get(), s.m_PopCount.get());
159 template <class Stack>
160 void analyze( Stack& testStack )
162 cds_test::thread_pool& pool = get_pool();
164 size_t nThreadItems = s_nStackSize / s_nThreadCount;
165 std::vector<size_t> aThread;
166 aThread.resize( s_nThreadCount );
168 for ( size_t i = 0; i < pool.size(); ++i ) {
169 Producer<Stack>& producer = static_cast<Producer<Stack>&>( pool.get( i ));
170 EXPECT_EQ( producer.m_nPushError, 0u ) << "Producer=" << i;
171 aThread[producer.id()] = producer.m_nEndItem - 1;
173 EXPECT_FALSE( testStack.empty());
175 std::unique_ptr< uint8_t[] > uarr( new uint8_t[s_nStackSize] );
176 uint8_t * arr = uarr.get();
177 memset( arr, 0, sizeof( arr[0] ) * s_nStackSize );
179 auto time_start = std::chrono::steady_clock::now();
182 while ( testStack.pop( val )) {
184 ASSERT_LT( val.nNo, s_nStackSize );
186 ASSERT_LT( val.nThread, s_nThreadCount );
187 ASSERT_EQ( aThread[val.nThread], val.nNo );
188 aThread[val.nThread]--;
190 propout() << std::make_pair( "pop_duration", std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - time_start));
192 size_t nTotalItems = nThreadItems * s_nThreadCount;
194 for ( size_t i = 0; i < nTotalItems; ++i ) {
195 EXPECT_EQ( arr[i], 1 ) << "i=" << i;
196 if ( ++nError > 10 ) {
197 ASSERT_EQ( arr[i], 1 );
203 CDSSTRESS_TreiberStack( stack_push )
204 CDSSTRESS_EliminationStack( stack_push )
205 //CDSSTRESS_FCStack( stack_push )
206 //CDSSTRESS_FCDeque( stack_push )