7 #include "tbb/task_scheduler_init.h" 8 #include "tbb/task_scheduler_observer.h" 9 #include "tbb/tbb_thread.h" 10 #include "tbb/tick_count.h" 15 namespace Concurrency {
25 declareProperty(
"ThreadInitTools", m_threadInitTools,
"ToolHandleArray of IThreadInitTools" );
35 warning() <<
"Base class could not be initialized" <<
endmsg;
39 if ( m_threadInitTools.retrieve().isFailure() ) {
40 error() <<
"Unable to retrieve ThreadInitTools Array" <<
endmsg;
44 if ( m_threadInitTools.size() != 0 ) {
45 info() <<
"retrieved " << m_threadInitTools.size() <<
" thread init tools" <<
endmsg;
47 info() <<
"no thread init tools attached" <<
endmsg;
58 warning() <<
"Looks like the ThreadPoolSvc was created, but thread pool " 59 <<
"was never initialized" <<
endmsg;
69 tbb::spin_mutex::scoped_lock lock( m_initMutex );
71 m_threadPoolSize = poolSize;
73 if ( msgLevel(
MSG::DEBUG ) ) debug() <<
"ThreadPoolSvc::initPool() poolSize = " << poolSize <<
endmsg;
87 if ( -100 != m_threadPoolSize ) {
88 if ( msgLevel(
MSG::DEBUG ) ) debug() <<
"Initialising a thread pool of size " << m_threadPoolSize <<
endmsg;
92 int thePoolSize = m_threadPoolSize;
93 if ( thePoolSize >= 0 ) thePoolSize += 1;
95 if ( m_threadPoolSize == -1 ) {
97 m_tbbSchedInit = std::make_unique<tbb::task_scheduler_init>();
98 thePoolSize = m_tbbSchedInit->default_num_threads();
99 m_threadPoolSize = thePoolSize;
100 }
else if ( m_threadPoolSize >= 0 ) {
102 m_tbbgc = std::make_unique<tbb::global_control>( global_control::max_allowed_parallelism, thePoolSize );
103 m_tbbSchedInit = std::make_unique<tbb::task_scheduler_init>( thePoolSize );
105 fatal() <<
"Unexpected ThreadPoolSize \"" << m_threadPoolSize <<
"\". Allowed negative values are " 106 <<
"-1 (use all available cores) and -100 (don't use a thread pool)" <<
endmsg;
113 m_barrier = std::make_unique<boost::barrier>( thePoolSize );
118 m_tbbgc = std::make_unique<tbb::global_control>( global_control::max_allowed_parallelism, 0 );
122 debug() <<
"Thread Pool initialization complete. Max task concurrency: " 123 << tbb::global_control::active_value( global_control::max_allowed_parallelism ) <<
endmsg;
133 tbb::spin_mutex::scoped_lock lock( m_initMutex );
134 if ( msgLevel(
MSG::DEBUG ) ) debug() <<
"ThreadPoolSvc::terminatePool()" <<
endmsg;
137 error() <<
"Trying to terminate uninitialized thread pool!" <<
endmsg;
142 const bool terminate =
true;
145 if ( msgLevel(
MSG::DEBUG ) ) debug() <<
"Thread pool termination complete!" <<
endmsg;
154 const std::string taskType = terminate ?
"termination" :
"initialization";
158 if ( m_tbbSchedInit ) {
161 for (
int i = 0; i < m_threadPoolSize; ++i ) {
162 if ( msgLevel(
MSG::DEBUG ) ) debug() <<
"creating ThreadInitTask " << i <<
endmsg;
163 tbb::task* t =
new ( tbb::task::allocate_root() )
164 ThreadInitTask( m_threadInitTools, m_barrier.get(), serviceLocator(), terminate );
167 tbb::task::enqueue( *t );
168 this_tbb_thread::sleep( tbb::tick_count::interval_t( .02 ) );
172 if ( msgLevel(
MSG::DEBUG ) ) debug() <<
"waiting at barrier for all ThreadInitTool to finish executing" <<
endmsg;
177 for (
auto& t : m_threadInitTools ) {
179 int numInit = t->nInit();
181 int expectedNumInit = terminate ? 0 : m_threadPoolSize;
182 if ( numInit != expectedNumInit ) {
184 ost <<
"not all threads " << ( terminate ?
"terminated" :
"initialized" ) <<
" for tool " << t <<
" : " 185 << t->nInit() <<
" out of " << m_threadPoolSize <<
" are currently active.";
202 if ( msgLevel(
MSG::DEBUG ) ) debug() <<
"launching ThreadInitTask " << taskType <<
"in this thread." <<
endmsg;
203 boost::barrier* noBarrier =
nullptr;
204 ThreadInitTask theTask( m_threadInitTools, noBarrier, serviceLocator(), terminate );
210 error() <<
"a ThreadInitTask failed to execute successfully" <<
endmsg;
237 error() <<
"initThisThread triggered, but thread already initialized" <<
endmsg;
241 boost::barrier* noBarrier =
nullptr;
242 ThreadInitTask theTask( m_threadInitTools, noBarrier, serviceLocator(),
false );
StatusCode finalize() override final
Finalise.
static GAUDI_API void setNumThreads(const std::size_t &nT)
StatusCode initialize() override
tbb::task * execute() override
Execute the task.
Define general base for Gaudi exception.
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
StatusCode terminatePool() override final
Terminate the thread pool and launch thread termination tasks.
Special TBB task used by ThreadPoolSvc to wrap execution of IThreadInitTools.
constexpr static const auto SUCCESS
virtual void initThisThread() override
#define GAUDI_NO_SANITIZE_ADDRESS
#define DECLARE_COMPONENT(type)
This class is used for returning status codes from appropriate routines.
StatusCode initialize() override final
Initialise.
thread_local bool ThreadInitDone
Base class used to extend a class implementing other interfaces.
A service which initializes a TBB thread pool.
constexpr static const auto FAILURE
StatusCode initPool(const int &poolSize) override final
Initialize the thread pool and launch the ThreadInitTasks.
StatusCode launchTasks(bool finalize=false)
Launch tasks to execute the ThreadInitTools.
Header file for std:chrono::duration-based Counters.
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.