OpenWalnut  1.5.0dev
WThreadedFunction_test.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WTHREADEDFUNCTION_TEST_H
26 #define WTHREADEDFUNCTION_TEST_H
27 
28 #include <memory>
29 #include <string>
30 
31 #include <cxxtest/TestSuite.h>
32 
33 #include "../WSharedObject.h"
34 #include "../WThreadedFunction.h"
35 
36 /**
37  * \class WThreadedFunctionTest
38  *
39  * Tests the WThreadedFunction class.
40  */
41 class WThreadedFunctionTest : public CxxTest::TestSuite
42 {
43  /**
44  * A threaded function.
45  */
46  class FuncType
47  {
48  public:
49  /**
50  * Constructor, initialize some stuff.
51  *
52  * \param value An int value.
53  */
54  FuncType( int value ) // NOLINT
55  : m_input( new int( value ) ) // NOLINT
56  {
57  // init stuff here
58  m_result.getWriteTicket()->get() = 0;
59  m_stopped.getWriteTicket()->get() = false;
60 
61  if( value < 0 )
62  {
63  value = -value;
64  }
65  }
66 
67  /**
68  * This is the actual thread function.
69  *
70  * \param shutdown A flag indicating the thread is supposed to stop.
71  */
72  void operator() ( std::size_t, std::size_t, WBoolFlag const& shutdown )
73  {
74  for( int i = 1; i <= *m_input.get() && !shutdown(); ++i )
75  {
76  m_result.getWriteTicket()->get() += i;
77  }
78  if( shutdown() )
79  {
80  m_stopped.getWriteTicket()->get() = true;
81  }
82  sleep( 1 );
83  }
84 
85  /**
86  * Check if the thread was ordered to stop.
87  *
88  * \return true, if the thread was ordered to stop
89  */
90  bool stopped()
91  {
92  return m_stopped.getReadTicket()->get();
93  }
94 
95  /**
96  * A method to extract the result.
97  *
98  * \return The result of the threaded computation.
99  */
100  int getResult()
101  {
102  return m_result.getReadTicket()->get();
103  }
104 
105  /**
106  * Reset everything.
107  */
108  void reset()
109  {
110  m_result.getWriteTicket()->get() = 0;
111  }
112 
113  private:
114  //! the input data
115  std::shared_ptr< int const > m_input;
116 
117  //! the result
119 
120  //! thread stopped?
122  };
123 
124  /**
125  * A function that throws exceptions.
126  */
128  {
129  public:
130  /**
131  * The function.
132  */
133  void operator() ( std::size_t, std::size_t, WBoolFlag& )
134  {
135  throw WException( std::string( "Test!" ) );
136  }
137  };
138 
139 public:
140  /**
141  * A function computed by multiple threads should correctly set
142  * its status and compute the correct results.
143  */
145  {
146  std::shared_ptr< FuncType > func( new FuncType( 5 ) );
147  // test 1 thread
148  {
149  WThreadedFunction< FuncType > f( 1, func );
150 
151  TS_ASSERT_EQUALS( f.status(), W_THREADS_INITIALIZED );
152  f.run();
153  TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
154  f.wait();
155  TS_ASSERT_EQUALS( f.status(), W_THREADS_FINISHED );
156 
157  TS_ASSERT_EQUALS( func->getResult(), 15 );
158  func->reset();
159 
160  f.run();
161  TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
162  f.wait();
163 
164  TS_ASSERT_EQUALS( func->getResult(), 15 );
165 
166  f.run();
167  TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
168  f.wait();
169 
170  TS_ASSERT_EQUALS( func->getResult(), 30 );
171  func->reset();
172  }
173  // test 2 threads
174  {
175  WThreadedFunction< FuncType > f( 2, func );
176 
177  TS_ASSERT_EQUALS( f.status(), W_THREADS_INITIALIZED );
178  f.run();
179  TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
180  f.wait();
181  TS_ASSERT_EQUALS( f.status(), W_THREADS_FINISHED );
182 
183  TS_ASSERT_EQUALS( func->getResult(), 30 );
184  func->reset();
185  }
186  // test 5 threads
187  {
188  WThreadedFunction< FuncType > f( 5, func );
189 
190  TS_ASSERT_EQUALS( f.status(), W_THREADS_INITIALIZED );
191  f.run();
192  TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
193  f.wait();
194  TS_ASSERT_EQUALS( f.status(), W_THREADS_FINISHED );
195 
196  TS_ASSERT_EQUALS( func->getResult(), 75 );
197  func->reset();
198  }
199  }
200 
201  /**
202  * Status should be set correctly when threads are ordered to stop.
203  */
205  {
206  std::shared_ptr< FuncType > func( new FuncType( 100000000 ) );
207  WThreadedFunction< FuncType > f( 6, func );
208 
209  TS_ASSERT_EQUALS( f.status(), W_THREADS_INITIALIZED );
210  f.run();
211  TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
212  f.stop();
213  TS_ASSERT_EQUALS( f.status(), W_THREADS_STOP_REQUESTED );
214  f.wait();
215  TS_ASSERT_EQUALS( f.status(), W_THREADS_ABORTED );
216 
217  TS_ASSERT( func->stopped() );
218  func->reset();
219  }
220 
221  /**
222  * The stop condition should be notified correctly.
223  */
225  {
226  std::shared_ptr< FuncType > func( new FuncType( 5 ) );
227  WThreadedFunction< FuncType > f( 6, func );
228 
229  TS_ASSERT_EQUALS( f.status(), W_THREADS_INITIALIZED );
230  f.run();
231  TS_ASSERT_EQUALS( f.status(), W_THREADS_RUNNING );
232  f.getThreadsDoneCondition()->wait();
233  TS_ASSERT_EQUALS( f.status(), W_THREADS_FINISHED );
234 
235  TS_ASSERT_EQUALS( func->getResult(), 90 );
236  func->reset();
237  }
238 
239  /**
240  * Exceptions should lead to the status beeing changed to W_THREADS_ABORTED. Also,
241  * exceptions should be forwarded to the exception handler.
242  */
244  {
245  std::shared_ptr< ExceptionalFuncType > func( new ExceptionalFuncType );
247  f.subscribeExceptionSignal( boost::bind( &WThreadedFunctionTest::handleException, this, boost::placeholders::_1 ) );
248 
249  m_exceptionCounter.getWriteTicket()->get() = 0;
250 
251  f.run();
252  f.wait();
253 
254  TS_ASSERT_EQUALS( f.status(), W_THREADS_ABORTED );
255  TS_ASSERT_EQUALS( m_exceptionCounter.getReadTicket()->get(), 7 );
256  }
257 
258 private:
259  /**
260  * Exception callback.
261  */
263  {
265  }
266 
267  //! a counter
269 };
270 
271 #endif // WTHREADEDFUNCTION_TEST_H
Basic exception handler.
Definition: WException.h:39
ReadTicket getReadTicket() const
Returns a ticket to get read access to the contained data.
WriteTicket getWriteTicket(bool suppressNotify=false) const
Returns a ticket to get write access to the contained data.
std::shared_ptr< WCondition > getThreadsDoneCondition()
Returns a condition that gets fired when all threads have finished.
WThreadedFunctionStatus status()
Get the status of the threads.
void subscribeExceptionSignal(ExceptionFunction func)
Subscribe a function to an exception signal.
void operator()(std::size_t, std::size_t, WBoolFlag &)
The function.
void operator()(std::size_t, std::size_t, WBoolFlag const &shutdown)
This is the actual thread function.
WSharedObject< int > m_result
the result
FuncType(int value)
Constructor, initialize some stuff.
bool stopped()
Check if the thread was ordered to stop.
int getResult()
A method to extract the result.
std::shared_ptr< int const > m_input
the input data
WSharedObject< bool > m_stopped
thread stopped?
Tests the WThreadedFunction class.
void testExceptionHandling()
Exceptions should lead to the status beeing changed to W_THREADS_ABORTED.
void handleException(WException const &)
Exception callback.
void testStopThreads()
Status should be set correctly when threads are ordered to stop.
void testMultipleThreads()
A function computed by multiple threads should correctly set its status and compute the correct resul...
WSharedObject< int > m_exceptionCounter
a counter
void testStopCondition()
The stop condition should be notified correctly.
Creates threads that computes a function in a multithreaded fashion.
virtual void wait()
Wait for all threads to stop.
virtual void stop()
Request all threads to stop.
virtual void run()
Starts the threads.