3 #include "cppunit/thread.h"
4 #include "stack/stack_type.h"
5 #include "print_deque_stat.h"
7 // Multi-threaded stack test for push operation
10 #define TEST_CASE( Q ) void Q() { test_unbounded< Types<SimpleValue>::Q >(); }
11 #define TEST_ELIMINATION( Q ) void Q() { test_elimination< Types<SimpleValue>::Q >(); }
12 #define TEST_BOUNDED( Q ) void Q() { test_bounded< Types<SimpleValue>::Q >(); }
15 static size_t s_nThreadCount = 8;
16 static size_t s_nStackSize = 10000000;
17 static size_t s_nEliminationSize = 4;
23 SimpleValue(): nNo(0), nThread(0) {}
24 SimpleValue( size_t n ): nNo(n), nThread(0) {}
25 size_t getNo() const { return nNo; }
29 class Stack_Push: public CppUnitMini::TestCase
31 template <class Stack>
32 class Thread: public CppUnitMini::TestThread
34 virtual TestThread * clone()
36 return new Thread( *this );
46 Thread( CppUnitMini::ThreadPool& pool, Stack& s )
47 : CppUnitMini::TestThread( pool )
51 : CppUnitMini::TestThread( src )
52 , m_Stack( src.m_Stack )
57 return reinterpret_cast<Stack_Push&>( m_Pool.m_Test );
62 cds::threading::Manager::attachThread();
66 cds::threading::Manager::detachThread();
71 m_fTime = m_Timer.duration();
75 v.nThread = m_nThreadNo;
76 for ( v.nNo = m_nStartItem; v.nNo < m_nEndItem; ++v.nNo ) {
77 if ( !m_Stack.push( v ))
81 m_fTime = m_Timer.duration() - m_fTime;
86 void setUpParams( const CppUnitMini::TestCfg& cfg ) {
87 s_nThreadCount = cfg.getULong("ThreadCount", 8 );
88 s_nStackSize = cfg.getULong("StackSize", 10000000 );
89 s_nEliminationSize = cfg.getULong("EliminationSize", 4 );
92 template <class Stack>
93 void analyze( CppUnitMini::ThreadPool& pool, Stack& testStack )
95 size_t nThreadItems = s_nStackSize / s_nThreadCount;
96 std::vector<size_t> aThread;
97 aThread.resize(s_nThreadCount);
100 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
101 Thread<Stack> * pThread = reinterpret_cast<Thread<Stack> *>(*it);
102 fTime += pThread->m_fTime;
103 if ( pThread->m_nPushError != 0 )
104 CPPUNIT_MSG(" ERROR: thread push error count=" << pThread->m_nPushError );
105 aThread[ pThread->m_nThreadNo] = pThread->m_nEndItem - 1;
107 CPPUNIT_MSG( " Duration=" << (fTime / s_nThreadCount) );
108 CPPUNIT_ASSERT( !testStack.empty() )
110 size_t * arr = new size_t[ s_nStackSize ];
111 memset(arr, 0, sizeof(arr[0]) * s_nStackSize );
113 cds::OS::Timer timer;
114 CPPUNIT_MSG( " Pop (single-threaded)..." );
117 while ( testStack.pop( val )) {
119 ++arr[ val.getNo() ];
120 CPPUNIT_ASSERT( val.nThread < s_nThreadCount);
121 CPPUNIT_ASSERT( aThread[val.nThread] == val.nNo );
122 aThread[val.nThread]--;
124 CPPUNIT_MSG( " Duration=" << timer.duration() );
126 size_t nTotalItems = nThreadItems * s_nThreadCount;
128 for ( size_t i = 0; i < nTotalItems; ++i ) {
130 CPPUNIT_MSG( " ERROR: Item " << i << " has not been pushed" );
131 CPPUNIT_ASSERT( ++nError > 10 );
138 // Unbounded stack test
139 template <class Stack>
140 void test_unbounded()
146 // Unbounded elimination stack test
147 template <class Stack>
148 void test_elimination()
150 Stack testStack( s_nEliminationSize );
152 check_elimination_stat( testStack.statistics() );
154 void check_elimination_stat( cds::container::treiber_stack::empty_stat const& )
156 void check_elimination_stat( cds::container::treiber_stack::stat<> const& s )
158 CPPUNIT_CHECK( s.m_PushCount.get() == s.m_PopCount.get() );
161 // Bounded stack test
162 template <class Stack>
165 Stack testStack( s_nStackSize );
169 template <class Stack>
170 void test( Stack& testStack )
172 CppUnitMini::ThreadPool pool( *this );
173 pool.add( new Thread<Stack>( pool, testStack ), s_nThreadCount );
176 size_t nThreadItemCount = s_nStackSize / s_nThreadCount;
177 for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
178 Thread<Stack> * pThread = reinterpret_cast<Thread<Stack> *>(*it);
179 pThread->m_nStartItem = nStart;
180 nStart += nThreadItemCount;
181 pThread->m_nEndItem = nStart;
184 CPPUNIT_MSG( " Push test, thread count=" << s_nThreadCount
185 << " items=" << (nThreadItemCount * s_nThreadCount)
189 analyze( pool, testStack );
190 CPPUNIT_MSG( testStack.statistics() );
194 # include "stack/stack_defs.h"
195 CDSUNIT_DECLARE_TreiberStack
196 CDSUNIT_DECLARE_EliminationStack
197 CDSUNIT_DECLARE_FCStack
198 CDSUNIT_DECLARE_FCDeque
199 CDSUNIT_DECLARE_MichaelDeque
200 CDSUNIT_DECLARE_StdStack
202 CPPUNIT_TEST_SUITE(Stack_Push)
203 CDSUNIT_TEST_TreiberStack
204 CDSUNIT_TEST_EliminationStack
207 CDSUNIT_TEST_MichaelDeque
208 CDSUNIT_TEST_StdStack
209 CPPUNIT_TEST_SUITE_END();
213 CPPUNIT_TEST_SUITE_REGISTRATION(stack::Stack_Push);