Logo ROOT  
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//=============================================================================
31using 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
34const size_t g_sleeptime = 2; // in secs.
35const size_t g_multTasks = 10;
36//=============================================================================
37
38enum EProc {start, clean};
39
40class TTestTask: public TThreadPoolTaskImp<TTestTask, EProc> {
41public:
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
51private:
52 unsigned long m_tid;
53};
54ostream &operator<< (ostream &_stream, const TTestTask &_task)
55{
56 _stream << _task.threadID();
57 return _stream;
58}
59
60//=============================================================================
61void 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}
TBuffer & operator<<(TBuffer &buf, const Tmpl *obj)
Definition: TBuffer.h:398
static Int_t Sleep(ULong_t secs, ULong_t nanos=0)
Static method to sleep the calling thread.
Definition: TThread.cxx:746
static Long_t SelfId()
Static method returning the id for the current thread.
Definition: TThread.cxx:548
static constexpr double L