Removed old map tests
[libcds.git] / tests / unit / lock / spinlock.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-2016
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 "cppunit/thread.h"
32
33 #include <cds/lock/spinlock.h>
34
35 // Multi-threaded stack test for push operation
36 namespace lock {
37
38 #define TEST_CASE( N, L )   void N() { test<L>(); }
39
40     namespace {
41         static size_t s_nThreadCount = 8;
42         static size_t s_nLoopCount = 1000000    ;     // loop count per thread
43
44         static size_t   s_nSharedInt;
45     }
46
47     class Spinlock_MT: public CppUnitMini::TestCase
48     {
49         template <class LOCK>
50         class Thread: public CppUnitMini::TestThread
51         {
52             virtual TestThread *    clone()
53             {
54                 return new Thread( *this );
55             }
56         public:
57             LOCK&               m_Lock;
58             double              m_fTime;
59
60         public:
61             Thread( CppUnitMini::ThreadPool& pool, LOCK& l )
62                 : CppUnitMini::TestThread( pool )
63                 , m_Lock( l )
64             {}
65             Thread( Thread& src )
66                 : CppUnitMini::TestThread( src )
67                 , m_Lock( src.m_Lock )
68             {}
69
70             Spinlock_MT&  getTest()
71             {
72                 return reinterpret_cast<Spinlock_MT&>( m_Pool.m_Test );
73             }
74
75             virtual void init()
76             {}
77             virtual void fini()
78             {}
79
80             virtual void test()
81             {
82                 m_fTime = m_Timer.duration();
83
84                 for ( size_t i  = 0; i < s_nLoopCount; ++i ) {
85                     m_Lock.lock();
86                     ++s_nSharedInt;
87                     m_Lock.unlock();
88                 }
89
90                 m_fTime = m_Timer.duration() - m_fTime;
91             }
92         };
93
94     protected:
95         void setUpParams( const CppUnitMini::TestCfg& cfg ) {
96             s_nThreadCount = cfg.getULong("ThreadCount", 8 );
97             s_nLoopCount = cfg.getULong("LoopCount", 1000000 );
98         }
99
100         template <class LOCK>
101         void test()
102         {
103             LOCK    testLock;
104
105             for ( size_t nThreadCount = 1; nThreadCount <= s_nThreadCount; nThreadCount *= 2 ) {
106                 s_nSharedInt = 0;
107
108                 CppUnitMini::ThreadPool pool( *this );
109                 pool.add( new Thread<LOCK>( pool, testLock ), nThreadCount );
110
111                 CPPUNIT_MSG( "   Lock test, thread count=" << nThreadCount
112                     << " loop per thread=" << s_nLoopCount
113                     << "...");
114                 cds::OS::Timer      timer;
115                 pool.run();
116                 CPPUNIT_MSG( "     Duration=" << timer.duration() );
117
118                 CPPUNIT_ASSERT_EX( s_nSharedInt == nThreadCount * s_nLoopCount,
119                     "Expected=" << nThreadCount * s_nLoopCount
120                     << " real=" << s_nSharedInt );
121             }
122         }
123
124         typedef cds::sync::spin_lock<cds::backoff::exponential<cds::backoff::hint, cds::backoff::yield> > Spinlock_exp;
125
126         typedef cds::sync::reentrant_spin_lock<unsigned int, cds::backoff::exponential<cds::backoff::hint, cds::backoff::yield> > reentrantSpin_exp;
127         typedef cds::sync::reentrant_spin_lock<unsigned int, cds::backoff::yield> reentrantSpin_yield;
128         typedef cds::sync::reentrant_spin_lock<unsigned int, cds::backoff::hint> reentrantSpin_hint;
129         typedef cds::sync::reentrant_spin_lock<unsigned int, cds::backoff::empty> reentrantSpin_empty;
130
131         TEST_CASE(spinLock_exp,         Spinlock_exp );
132         TEST_CASE(spinLock_yield,       cds::sync::spin_lock<cds::backoff::yield> );
133         TEST_CASE(spinLock_hint,        cds::sync::spin_lock<cds::backoff::hint> );
134         TEST_CASE(spinLock_empty,       cds::sync::spin_lock<cds::backoff::empty> );
135         TEST_CASE( spinLock_yield_lock, cds::lock::Spinlock<cds::backoff::yield> );
136         TEST_CASE( spinLock_hint_lock, cds::lock::Spinlock<cds::backoff::hint> );
137         TEST_CASE( spinLock_empty_lock, cds::lock::Spinlock<cds::backoff::empty> );
138
139         TEST_CASE( reentrantSpinLock32, cds::sync::reentrant_spin32 );
140         TEST_CASE( reentrantSpinLock64, cds::sync::reentrant_spin64 );
141         TEST_CASE( reentrantSpinLock32_lock, cds::lock::ReentrantSpin32 );
142         TEST_CASE( reentrantSpinLock64_lock, cds::lock::ReentrantSpin64 );
143
144         TEST_CASE(reentrantSpinlock_exp,        reentrantSpin_exp );
145         TEST_CASE(reentrantSpinlock_yield,      reentrantSpin_yield );
146         TEST_CASE(reentrantSpinlock_hint,       reentrantSpin_hint );
147         TEST_CASE(reentrantSpinlock_empty,      reentrantSpin_empty );
148
149     protected:
150         CPPUNIT_TEST_SUITE(Spinlock_MT)
151             CPPUNIT_TEST(spinLock_exp);
152             CPPUNIT_TEST(spinLock_yield);
153             CPPUNIT_TEST(spinLock_hint);
154             CPPUNIT_TEST(spinLock_empty);
155
156             CPPUNIT_TEST(reentrantSpinLock32);
157             CPPUNIT_TEST(reentrantSpinLock64);
158
159             CPPUNIT_TEST(reentrantSpinlock_exp)
160             CPPUNIT_TEST(reentrantSpinlock_yield)
161             CPPUNIT_TEST(reentrantSpinlock_hint)
162             CPPUNIT_TEST(reentrantSpinlock_empty)
163         CPPUNIT_TEST_SUITE_END();
164     };
165
166 } // namespace lock
167
168 CPPUNIT_TEST_SUITE_REGISTRATION(lock::Spinlock_MT);