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