535463fec69537a07924e7261109d873a571da0c
[libcds.git] / tests / cppunit / thread.h
1 //$$CDS-header$$
2
3 #ifndef __CPPUNIT_THREAD_H
4 #define __CPPUNIT_THREAD_H
5
6 #include "cppunit/cppunit_mini.h"
7 #include <boost/thread.hpp>
8 #include <cds/os/timer.h>
9 #include <cds/threading/model.h>    // for attach/detach thread
10 #include <cds/cxx11_atomic.h>
11
12 namespace CppUnitMini {
13     static inline unsigned int Rand( unsigned int nMax )
14     {
15         double rnd = double( rand() ) / double( RAND_MAX );
16         unsigned int n = (unsigned int) (rnd * nMax);
17         return n < nMax ? n : (n-1);
18     }
19
20     class ThreadPool;
21     class TestThread
22     {
23     protected:
24         typedef TestThread  Base;
25         friend class ThreadPool;
26
27         ThreadPool&         m_Pool;
28         boost::thread *     m_pThread;
29         cds::OS::Timer      m_Timer;
30         CDS_ATOMIC::atomic<bool>    m_bTimeElapsed;
31
32     public:
33         double              m_nDuration;
34         size_t              m_nThreadNo;
35
36     protected:
37         static void threadEntryPoint( TestThread * pThread );
38
39         TestThread( TestThread& src )
40             : m_Pool( src.m_Pool )
41             , m_pThread( NULL )
42             , m_bTimeElapsed( false )
43             , m_nDuration( 0 )
44             , m_nThreadNo( 0 )
45         {}
46
47         virtual ~TestThread()
48         {
49             if ( m_pThread )
50                 delete m_pThread;
51         }
52
53         virtual TestThread *    clone() = 0;
54
55         void create();
56         void run();
57
58         virtual void init() {}
59         virtual void test() = 0;
60         virtual void fini() {}
61         void stop()
62         {
63             m_bTimeElapsed.store( true, CDS_ATOMIC::memory_order_release );
64         }
65         bool time_elapsed() const
66         {
67             return m_bTimeElapsed.load( CDS_ATOMIC::memory_order_acquire );
68         }
69
70         bool check_timeout( size_t nMaxDuration )
71         {
72             return m_Timer.duration() > nMaxDuration;
73         }
74
75         void error(const char *in_macroName, const char *in_macro, const char *in_file, int in_line);
76
77     public:
78         TestThread( ThreadPool& pool )
79             : m_Pool( pool )
80             , m_pThread( NULL )
81             , m_nDuration( 0 )
82             , m_nThreadNo( 0 )
83         {}
84     };
85
86     class ThreadPool
87     {
88     public:
89         TestCase&                       m_Test;
90
91     private:
92         typedef std::vector< TestThread * >     thread_vector;
93
94         boost::thread_group             m_Pool;
95         thread_vector                   m_arrThreads;
96
97         boost::barrier * volatile       m_pBarrierStart;
98         boost::barrier * volatile       m_pBarrierDone;
99
100     public:
101         typedef thread_vector::iterator    iterator;
102
103     public:
104         ThreadPool( TestCase& tc )
105             : m_Test( tc )
106             , m_pBarrierStart( NULL )
107             , m_pBarrierDone( NULL )
108         {}
109         ~ThreadPool();
110
111         void    add( TestThread * pThread, size_t nCount );
112
113         void    run();
114         void    run( unsigned int nDuration );
115
116         void    onThreadInitDone( TestThread * pThread );
117         void    onThreadTestDone( TestThread * pThread );
118         void    onThreadFiniDone( TestThread * pThread );
119
120         iterator begin() { return m_arrThreads.begin(); }
121         iterator end()   { return m_arrThreads.end() ;   }
122
123         double  avgDuration() const
124         {
125             double nDur = 0;
126             for ( size_t i = 0; i < m_arrThreads.size(); ++i )
127                 nDur += m_arrThreads[i]->m_nDuration;
128             return nDur / m_arrThreads.size();
129         }
130     };
131 }
132
133 #endif    // #ifndef __CPPUNIT_THREAD_H