Merge branch 'dev'
[libcds.git] / tests / cppunit / thread.cpp
1 //$$CDS-header$$
2
3 #include <chrono>
4 #include <cds/details/defs.h> // TSan annotations
5 #include "cppunit/thread.h"
6
7 namespace CppUnitMini {
8
9     void TestThread::threadEntryPoint( TestThread * pInst )
10     {
11         pInst->run();
12     }
13
14     void TestThread::create()
15     {
16         m_pThread = new boost::thread( threadEntryPoint, this );
17     }
18
19     void TestThread::run()
20     {
21         try {
22             init();
23             m_Pool.onThreadInitDone( this );
24
25             test();
26             m_Pool.onThreadTestDone( this );
27
28             fini();
29             m_Pool.onThreadFiniDone( this );
30         }
31         catch ( std::exception& ex )
32         {
33             m_Pool.m_Test.message( "EXCEPTION in working thread: ");
34             m_Pool.m_Test.message( ex.what() );
35         }
36     }
37
38     void TestThread::error(const char *in_macroName, const char *in_macro, const char *in_file, int in_line)
39     {
40         m_Pool.m_Test.error( in_macroName, in_macro, in_file, in_line );
41     }
42
43
44     ThreadPool::~ThreadPool()
45     {
46         CDS_TSAN_ANNOTATE_IGNORE_RW_BEGIN;
47
48         delete m_pBarrierStart;
49         delete m_pBarrierDone;
50
51         for ( size_t i = 0; i < m_arrThreads.size(); ++i )
52             delete m_arrThreads[i];
53         m_arrThreads.resize( 0 );
54
55         CDS_TSAN_ANNOTATE_IGNORE_RW_END;
56     }
57
58     void    ThreadPool::add( TestThread * pThread, size_t nCount )
59     {
60         pThread->m_nThreadNo = m_arrThreads.size();
61         m_arrThreads.push_back( pThread );
62         while ( --nCount ) {
63             TestThread * p = pThread->clone();
64             if ( p ) {
65                 p->m_nThreadNo = m_arrThreads.size();
66                 m_arrThreads.push_back( p );
67             }
68         }
69     }
70
71     void    ThreadPool::run()
72     {
73         const size_t nThreadCount = m_arrThreads.size();
74         m_pBarrierStart = new boost::barrier( (unsigned int) nThreadCount );
75         // nThreadCount threads + current thread
76         m_pBarrierDone = new boost::barrier( (unsigned int) (nThreadCount + 1) );
77
78         for ( size_t i = 0; i < nThreadCount; ++i )
79             m_arrThreads[i]->create();
80
81         // Wait while all threads is done
82         m_pBarrierDone->wait();
83         std::this_thread::sleep_for(std::chrono::milliseconds(500));
84     }
85
86     void ThreadPool::run( unsigned int nDuration )
87     {
88         const size_t nThreadCount = m_arrThreads.size();
89         m_pBarrierStart = new boost::barrier( (unsigned int) nThreadCount );
90         m_pBarrierDone = new boost::barrier( (unsigned int) (nThreadCount + 1) );
91
92         for ( size_t i = 0; i < nThreadCount; ++i )
93             m_arrThreads[i]->create();
94
95         auto stEnd(std::chrono::steady_clock::now() + std::chrono::seconds( nDuration ));
96         do {
97             std::this_thread::sleep_until( stEnd );
98         } while ( std::chrono::steady_clock::now() < stEnd );
99
100         for ( size_t i = 0; i < nThreadCount; ++i )
101             m_arrThreads[i]->stop();
102
103         // Wait while all threads is done
104         m_pBarrierDone->wait();
105         std::this_thread::sleep_for(std::chrono::milliseconds(500));
106     }
107
108     void    ThreadPool::onThreadInitDone( TestThread * pThread )
109     {
110         // Calls in context of caller thread
111         // Wait while all threads started
112         m_pBarrierStart->wait();
113
114         pThread->m_Timer.reset();
115     }
116
117     void    ThreadPool::onThreadTestDone( TestThread * pThread )
118     {
119         // Calls in context of caller thread
120         pThread->m_nDuration = pThread->m_Timer.duration();
121     }
122
123     void    ThreadPool::onThreadFiniDone( TestThread * /*pThread*/ )
124     {
125         // Calls in context of caller thread
126         // Wait while all threads done
127         m_pBarrierDone->wait();
128     }
129 }