issue#11: cds: changed __CDS_ guard prefix to CDSLIB_ for all .h files
[libcds.git] / tests / unit / lock / spinlock.cpp
1 //$$CDS-header$$
2
3 #include "cppunit/thread.h"
4
5 #include <cds/lock/spinlock.h>
6
7 // Multi-threaded stack test for push operation
8 namespace lock {
9
10 #define TEST_CASE( N, L )   void N() { test<L>(); }
11
12     namespace {
13         static size_t s_nThreadCount = 8;
14         static size_t s_nLoopCount = 1000000    ;     // loop count per thread
15
16         static size_t   s_nSharedInt;
17     }
18
19     class Spinlock_MT: public CppUnitMini::TestCase
20     {
21         template <class LOCK>
22         class Thread: public CppUnitMini::TestThread
23         {
24             virtual TestThread *    clone()
25             {
26                 return new Thread( *this );
27             }
28         public:
29             LOCK&               m_Lock;
30             double              m_fTime;
31
32         public:
33             Thread( CppUnitMini::ThreadPool& pool, LOCK& l )
34                 : CppUnitMini::TestThread( pool )
35                 , m_Lock( l )
36             {}
37             Thread( Thread& src )
38                 : CppUnitMini::TestThread( src )
39                 , m_Lock( src.m_Lock )
40             {}
41
42             Spinlock_MT&  getTest()
43             {
44                 return reinterpret_cast<Spinlock_MT&>( m_Pool.m_Test );
45             }
46
47             virtual void init()
48             {}
49             virtual void fini()
50             {}
51
52             virtual void test()
53             {
54                 m_fTime = m_Timer.duration();
55
56                 for ( size_t i  = 0; i < s_nLoopCount; ++i ) {
57                     m_Lock.lock();
58                     ++s_nSharedInt;
59                     m_Lock.unlock();
60                 }
61
62                 m_fTime = m_Timer.duration() - m_fTime;
63             }
64         };
65
66     protected:
67         void setUpParams( const CppUnitMini::TestCfg& cfg ) {
68             s_nThreadCount = cfg.getULong("ThreadCount", 8 );
69             s_nLoopCount = cfg.getULong("LoopCount", 1000000 );
70         }
71
72         template <class LOCK>
73         void test()
74         {
75             LOCK    testLock;
76
77             for ( size_t nThreadCount = 1; nThreadCount <= s_nThreadCount; nThreadCount *= 2 ) {
78                 s_nSharedInt = 0;
79
80                 CppUnitMini::ThreadPool pool( *this );
81                 pool.add( new Thread<LOCK>( pool, testLock ), nThreadCount );
82
83                 CPPUNIT_MSG( "   Lock test, thread count=" << nThreadCount
84                     << " loop per thread=" << s_nLoopCount
85                     << "...");
86                 cds::OS::Timer      timer;
87                 pool.run();
88                 CPPUNIT_MSG( "     Duration=" << timer.duration() );
89
90                 CPPUNIT_ASSERT_EX( s_nSharedInt == nThreadCount * s_nLoopCount,
91                     "Expected=" << nThreadCount * s_nLoopCount
92                     << " real=" << s_nSharedInt );
93             }
94         }
95
96         typedef cds::lock::Spinlock<cds::backoff::exponential<cds::backoff::hint, cds::backoff::yield> > Spinlock_exp;
97
98         typedef cds::lock::ReentrantSpinT<unsigned int, cds::backoff::exponential<cds::backoff::hint, cds::backoff::yield> > reentrantSpin_exp;
99         typedef cds::lock::ReentrantSpinT<unsigned int, cds::backoff::yield> reentrantSpin_yield;
100         typedef cds::lock::ReentrantSpinT<unsigned int, cds::backoff::hint> reentrantSpin_hint;
101         typedef cds::lock::ReentrantSpinT<unsigned int, cds::backoff::empty> reentrantSpin_empty;
102
103         TEST_CASE(spinLock_exp,         Spinlock_exp );
104         TEST_CASE(spinLock_yield,       cds::lock::Spinlock<cds::backoff::yield> );
105         TEST_CASE(spinLock_hint,        cds::lock::Spinlock<cds::backoff::hint> );
106         TEST_CASE(spinLock_empty,       cds::lock::Spinlock<cds::backoff::empty> );
107
108         TEST_CASE(reentrantSpinLock,    cds::lock::ReentrantSpin    );
109         TEST_CASE(reentrantSpinLock32,  cds::lock::ReentrantSpin32  );
110         TEST_CASE(reentrantSpinLock64,  cds::lock::ReentrantSpin64  );
111
112         TEST_CASE(reentrantSpinlock_exp,        reentrantSpin_exp );
113         TEST_CASE(reentrantSpinlock_yield,      reentrantSpin_yield );
114         TEST_CASE(reentrantSpinlock_hint,       reentrantSpin_hint );
115         TEST_CASE(reentrantSpinlock_empty,      reentrantSpin_empty );
116
117     protected:
118         CPPUNIT_TEST_SUITE(Spinlock_MT)
119             CPPUNIT_TEST(spinLock_exp);
120             CPPUNIT_TEST(spinLock_yield);
121             CPPUNIT_TEST(spinLock_hint);
122             CPPUNIT_TEST(spinLock_empty);
123
124             CPPUNIT_TEST(reentrantSpinLock);
125             CPPUNIT_TEST(reentrantSpinLock32);
126             CPPUNIT_TEST(reentrantSpinLock64);
127
128             CPPUNIT_TEST(reentrantSpinlock_exp)
129             CPPUNIT_TEST(reentrantSpinlock_yield)
130             CPPUNIT_TEST(reentrantSpinlock_hint)
131             CPPUNIT_TEST(reentrantSpinlock_empty)
132         CPPUNIT_TEST_SUITE_END();
133     };
134
135 } // namespace lock
136
137 CPPUNIT_TEST_SUITE_REGISTRATION(lock::Spinlock_MT);