Logo ROOT   6.10/09
Reference Guide
stressThreadPool.C
Go to the documentation of this file.
1 /// \file
2 /// \ingroup tutorial_thread
3 ///
4 /// Usage:
5 ///
6 /// ~~~{.cpp}
7 /// root [0] .L stressThreadPool.C++
8 /// root [1] stressThreadPool(5, true)
9 /// ~~~
10 ///
11 /// where 5 is a number of Threads in the pool
12 /// there will be then nThreads * 10 tasks pushed to the test
13 ///
14 /// \macro_code
15 ///
16 /// \author Victor Perevovchikov
17 
18 // STD
19 #include <iostream>
20 #include <iterator>
21 #include <vector>
22 #ifndef _WIN32
23 #include <unistd.h>
24 #endif
25 // ThreadPool
26 #include "TThreadPool.h"
27 // ROOT
28 #include "TThread.h"
29 
30 //=============================================================================
31 using namespace std;
32 //=============================================================================
33 // Don't set it less than 1, otherwise autotest won't be able to detect whether tests were successful or not
34 const size_t g_sleeptime = 2; // in secs.
35 const size_t g_multTasks = 10;
36 //=============================================================================
37 
38 enum EProc {start, clean};
39 
40 class TTestTask: public TThreadPoolTaskImp<TTestTask, EProc> {
41 public:
42  bool runTask(EProc /*_param*/) {
43  m_tid = TThread::SelfId();
44  TThread::Sleep(g_sleeptime, 0L);
45  return true;
46  }
47  unsigned long threadID() const {
48  return m_tid;
49  }
50 
51 private:
52  unsigned long m_tid;
53 };
54 ostream &operator<< (ostream &_stream, const TTestTask &_task)
55 {
56  _stream << _task.threadID();
57  return _stream;
58 }
59 
60 //=============================================================================
61 void stressThreadPool(size_t _numThreads = 5, bool _needDbg = false)
62 {
63  size_t numTasks(_numThreads * g_multTasks);
64  TThreadPool<TTestTask, EProc> threadPool(_numThreads, _needDbg);
65  vector <TTestTask> tasksList(numTasks);
66  // Pushing 4 * numTasks task in the pool
67  // We want to dain the task queue before pushing a next bunch of tasks (just to show you a Drain method ;) )
68  for (size_t j = 0; j < 4; ++j )
69  {
70  cout << "+++++++++ Starting iteration #" << j << " ++++++++++++"<< endl;
71  for (size_t i = 0; i < numTasks; ++i) {
72  threadPool.PushTask(tasksList[i], start);
73  }
74 
75  cout << "\n ****** Drain the tasks queue ******" << endl;
76  threadPool.Drain();
77  }
78  cout << "\n Stopping..." << endl;
79  threadPool.Stop(true);
80 
81  // ostream_iterator<TTestTask> out_it( cout, "\n" );
82  // copy( tasksList.begin(), tasksList.end(),
83  // out_it );
84 
85  typedef map<unsigned long, size_t> counter_t;
86  counter_t counter;
87  {
88  vector <TTestTask>::const_iterator iter = tasksList.begin();
89  vector <TTestTask>::const_iterator iter_end = tasksList.end();
90  for (; iter != iter_end; ++iter) {
91  counter_t::iterator found = counter.find(iter->threadID());
92  if (found == counter.end())
93  counter.insert(counter_t::value_type(iter->threadID(), 1));
94  else {
95  found->second = found->second + 1;
96  }
97  }
98  }
99 
100  cout << "\n************* RESULT ****************" << endl;
101 
102  counter_t::const_iterator iter = counter.begin();
103  counter_t::const_iterator iter_end = counter.end();
104  bool testOK = true;
105  for (; iter != iter_end; ++iter) {
106  cout << "Thread " << iter->first << " was used " << iter->second << " times\n";
107  // each thread suppose to be used equal amount of time,
108  // exactly (g_numTasks/g_numThreads) times
109  if (iter->second != g_multTasks)
110  testOK = false;
111  }
112 
113  cout << "ThreadPool: the simple test status: " << (testOK ? "OK" : "Failed") << endl;
114 }
RooArgList L(const RooAbsArg &v1)
STL namespace.
TBuffer & operator<<(TBuffer &buf, const Tmpl *obj)
Definition: TBuffer.h:390
static Long_t SelfId()
Static method returning the id for the current thread.
Definition: TThread.cxx:538
static Int_t Sleep(ULong_t secs, ULong_t nanos=0)
Static method to sleep the calling thread.
Definition: TThread.cxx:736