2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
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.
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.
31 #ifndef CDSTEST_THREAD_H
32 #define CDSTEST_THREAD_H
34 #include <gtest/gtest.h>
37 #include <condition_variable>
40 #include <cds/threading/model.h>
53 protected: // thread_pool interface
54 thread( thread const& sample );
65 virtual thread * clone() = 0;
66 virtual void test() = 0;
70 cds::threading::Manager::attachThread();
73 virtual void TearDown()
75 cds::threading::Manager::detachThread();
79 explicit thread( thread_pool& master, int type = 0 );
81 thread_pool& pool() { return m_pool; }
82 int type() const { return m_type; }
83 size_t id() const { return m_id; }
86 friend class thread_pool;
94 // Pool of test threads
98 explicit thread_pool( ::testing::Test& fixture )
99 : m_fixture( fixture )
100 , m_bRunning( false )
101 , m_bStopped( false )
107 for ( auto t : m_threads )
111 void add( thread * what )
113 m_threads.push_back( what );
116 void add( thread * what, size_t count )
119 for ( size_t i = 1; i < count; ++i ) {
120 thread * p = what->clone();
125 std::chrono::milliseconds run()
130 auto time_start = std::chrono::steady_clock::now();
133 m_cvStart.notify_all();
136 scoped_lock l( m_cvMutex );
137 while ( m_doneCount != m_threads.size() )
141 auto time_end = std::chrono::steady_clock::now();
143 m_cvStop.notify_all();
145 for ( auto t : m_threads )
148 return m_testDuration = std::chrono::duration_cast<std::chrono::milliseconds>( time_end - time_start );
151 size_t size() const { return m_threads.size(); }
152 thread& get( size_t idx ) const { return *m_threads.at( idx ); }
154 template <typename Fixture>
157 return static_cast<Fixture&>(m_fixture);
160 std::chrono::milliseconds duration() const { return m_testDuration; }
162 protected: // thread interface
165 return m_threads.size();
168 void ready_to_start( thread& /*who*/ )
170 // Called from test thread
172 // Wait for all thread created
173 scoped_lock l( m_cvMutex );
174 while ( !m_bRunning )
178 void thread_done( thread& /*who*/ )
180 // Called from test thread
183 scoped_lock l( m_cvMutex );
187 // Tell pool that the thread is done
188 m_cvDone.notify_all();
190 // Wait for all thread done
192 scoped_lock l( m_cvMutex );
193 while ( !m_bStopped )
201 ::testing::Test& m_fixture;
202 std::vector<thread *> m_threads;
204 typedef std::unique_lock<std::mutex> scoped_lock;
205 std::mutex m_cvMutex;
206 std::condition_variable m_cvStart;
207 std::condition_variable m_cvStop;
208 std::condition_variable m_cvDone;
210 volatile bool m_bRunning;
211 volatile bool m_bStopped;
212 volatile size_t m_doneCount;
214 std::chrono::milliseconds m_testDuration;
217 inline thread::thread( thread_pool& master, int type /*= 0*/ )
220 , m_id( master.get_next_id())
221 , m_impl( &thread::run, this )
224 inline thread::thread( thread const& sample )
225 : m_pool( sample.m_pool )
226 , m_type( sample.m_type )
227 , m_id( m_pool.get_next_id() )
228 , m_impl( &thread::run, this )
231 inline void thread::run()
234 m_pool.ready_to_start( *this );
236 m_pool.thread_done( *this );
240 } // namespace cds_test
242 #endif // CDSTEST_THREAD_H