ThreadPoolSvc.cpp
Go to the documentation of this file.
1 #include "ThreadPoolSvc.h"
2 
4 #include "ThreadInitTask.h"
5 
6 #include "tbb/task_scheduler_init.h"
7 #include "tbb/task_scheduler_observer.h"
8 #include "tbb/task.h"
9 #include "tbb/tick_count.h"
10 #include "tbb/tbb_thread.h"
11 
12 using namespace tbb;
13 
15 
16 //===========================================================================
17 
18 
19 ThreadPoolSvc::ThreadPoolSvc( const std::string& name, ISvcLocator* svcLoc ):
20  base_class(name,svcLoc),
21  m_init(false),
22  m_threadPoolSize(0),
23  m_threadInitTools(this),
24  m_tbbSchedInit(0),
25  m_barrier(0)
26 {
27 
28  declareProperty("ThreadInitTools", m_threadInitTools, "ToolHandleArray of IThreadInitTools");
29 
30 }
31 
32 //---------------------------------------------------------------------------
33 
35 
36  if (m_tbbSchedInit)
37  delete m_tbbSchedInit;
38 
39  if (m_barrier)
40  delete m_barrier;
41 
42 }
43 
44 //---------------------------------------------------------------------------
45 
48 
49  // Initialise mother class (read properties, ...)
51  if (!sc.isSuccess()) {
52  warning () << "Base class could not be initialized" << endmsg;
53  return StatusCode::FAILURE;
54  }
55 
56  if (m_threadInitTools.retrieve().isFailure()) {
57  error() << "Unable to retrieve ThreadInitTools Array"
58  << endmsg;
59 
60  return StatusCode::FAILURE;
61  } else {
62  if (m_threadInitTools.size() != 0) {
63  info() << "retrieved " << m_threadInitTools.size() << " thread init tools"
64  << endmsg;
65  } else {
66  info() << "no thread init tools attached"
67  << endmsg;
68  }
69  }
70 
71  return StatusCode::SUCCESS;
72 
73 }
74 
75 //---------------------------------------------------------------------------
76 
79 
80  if (!m_init) {
81  warning() << "Looks like the ThreadPoolSvc was created, but thread pool was never initialized"
82  << endmsg;
83  }
84 
85  return StatusCode::SUCCESS;
86 
87 }
88 
89 //---------------------------------------------------------------------------
90 
92 ThreadPoolSvc::initPool(const int& poolSize) {
93 
94  tbb::spin_mutex::scoped_lock lock( m_initMutex );
95 
96  m_threadPoolSize = poolSize;
97 
98  if (msgLevel(MSG::DEBUG))
99  debug() << "ThreadPoolSvc::initPool() poolSize = " << poolSize << endmsg;
100 
101  // -100 prevents the creation of the pool and the scheduler directly executes
102  // the tasks.
103  if (-100 != m_threadPoolSize){
104  if (msgLevel(MSG::DEBUG))
105  debug() << "Initialising a ThreadPool thread pool of size " << m_threadPoolSize
106  << endmsg;
107  // Leave -1 in case selected, increment otherwise
108  int thePoolSize=m_threadPoolSize;
109  if (thePoolSize!=-1)
110  thePoolSize+=1;
111  m_tbbSchedInit = new tbb::task_scheduler_init (thePoolSize);
112 
113  // execute the Thread Init Tools if there are any, and wait at barrier
114  if (m_threadInitTools.size() > 0) {
115  if (msgLevel(MSG::DEBUG))
116  debug() << "creating barrier of size " << m_threadPoolSize + 1 << endmsg;
117  m_barrier = new boost::barrier( m_threadPoolSize + 1 );
118 
119  // create ThreadInitTasks, wait until all have executed
120  for (int i=0; i<m_threadPoolSize; ++i) {
121  if (msgLevel(MSG::DEBUG))
122  debug() << "creating ThreadInitTask " << i << endmsg;
123  tbb::task* t = new(tbb::task::allocate_root())
124  ThreadInitTask( m_threadInitTools, m_barrier, serviceLocator() );
125 
126  tbb::task::enqueue( *t );
127  this_tbb_thread::sleep(tbb::tick_count::interval_t(.1));
128  }
129  }
130 
131  } else {
132  if (msgLevel(MSG::DEBUG))
133  debug() << "Thread pool size is one. Pool not initialised." << endmsg;
134 
135  if (m_threadInitTools.size() > 0) {
136  if (msgLevel(MSG::DEBUG))
137  debug() << "doing ThreadInitTask init in this thread" << endmsg;
138  ThreadInitTask theTask(m_threadInitTools, m_barrier, serviceLocator() );
139  theTask.execute();
140  }
141 
142  }
143 
144  if (m_barrier) {
145  if (msgLevel(MSG::DEBUG))
146  debug() << "waiting at barrier for all ThreadInitTool to finish executing" << endmsg;
147  m_barrier->wait();
148  }
149 
151  error() << "a ThreadInitTask failed to execute successfully" << endmsg;
152  return StatusCode::FAILURE;
153  }
154 
155  // check to make sure all Tools were initialized
156  for (auto t : m_threadInitTools) {
157  if (t->nInit() != (unsigned int)m_threadPoolSize && m_threadPoolSize != -100) {
158  error() << " not all threads initialized for tool " << t << " : "
159  << t->nInit() << " out of " << m_threadPoolSize
160  << endmsg;
161  return StatusCode::FAILURE;
162  }
163  }
164 
165  if (msgLevel(MSG::DEBUG))
166  debug() << " Thread Pool initialization complete!" << endmsg;
167 
168  m_init = true;
169 
170  return StatusCode::SUCCESS;
171 
172 }
173 
174 //---------------------------------------------------------------------------
175 
178 
180 
182  for ( ; ito != m_threadInitTools.end(); ++ito ) {
183  IThreadInitTool* it = &(**ito);
184  tools.push_back(it);
185  }
186 
187  return tools;
188 }
StatusCode initialize() override
Definition: Service.cpp:68
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
~ThreadPoolSvc()
Destructor.
bool isSuccess() const
Test for a status code of SUCCESS.
Definition: StatusCode.h:76
STL namespace.
Array of Handles to be used in lieu of vector of naked pointers to tools.
Definition: PropertyMgr.h:24
virtual StatusCode initPool(const int &poolSize)
T push_back(T...args)
iterator begin()
Definition: GaudiHandle.h:448
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
static bool execFailed()
def lock(file)
Definition: locker.py:16
#define DECLARE_SERVICE_FACTORY(x)
Definition: Service.h:361
virtual tbb::task * execute()
STL class.
virtual StatusCode initialize()
Initialise.
virtual std::vector< IThreadInitTool * > getThreadInitTools() const
list i
Definition: ana.py:128
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
virtual StatusCode finalize()
Finalise.
IThreadInitTool GaudiKernel/IThreadInitTool.h.