CMS 3D CMS Logo

WaitingTaskWithArenaHolder.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Concurrency
4 // Class : WaitingTaskWithArenaHolder
5 //
6 // Original Author: W. David Dagenhart
7 // Created: 6 December 2017
8 
12 
13 namespace edm {
14 
16 
17  // Note that the arena will be the one containing the thread
18  // that runs this constructor. This is the arena where you
19  // eventually intend for the task to be spawned.
21  : m_task(iTask), m_arena(std::make_shared<tbb::task_arena>(tbb::task_arena::attach())) {
22  m_task->increment_ref_count();
23  }
24 
26  if (m_task) {
27  doneWaiting(std::exception_ptr{});
28  }
29  }
30 
32  : m_task(iHolder.m_task), m_arena(iHolder.m_arena) {
33  m_task->increment_ref_count();
34  }
35 
37  : m_task(iOther.m_task), m_arena(std::move(iOther.m_arena)) {
38  iOther.m_task = nullptr;
39  }
40 
43  std::swap(m_task, tmp.m_task);
45  return *this;
46  }
47 
50  std::swap(m_task, tmp.m_task);
52  return *this;
53  }
54 
55  // This spawns the task. The arena is needed to get the task spawned
56  // into the correct arena of threads. Use of the arena allows doneWaiting
57  // to be called from a thread outside the arena of threads that will manage
58  // the task. doneWaiting can be called from a non-TBB thread.
59  void WaitingTaskWithArenaHolder::doneWaiting(std::exception_ptr iExcept) {
60  if (iExcept) {
61  m_task->dependentTaskFailed(iExcept);
62  }
63  //enqueue can run the task before we finish
64  // doneWaiting and some other thread might
65  // try to reuse this object. Resetting
66  // before enqueue avoids problems
67  auto task = m_task;
68  m_task = nullptr;
69  if (0 == task->decrement_ref_count()) {
70  // The enqueue call will cause a worker thread to be created in
71  // the arena if there is not one already.
72  m_arena->enqueue([task = task]() { tbb::task::spawn(*task); });
73  }
74  }
75 
76  // This next function is useful if you know from the context that
77  // m_arena (which is set when the constructor was executes) is the
78  // same arena in which you want to execute the doneWaiting function.
79  // It allows an optimization which avoids the enqueue step in the
80  // doneWaiting function.
81  //
82  // Be warned though that in general this function cannot be used.
83  // Spawning a task outside the correct arena could create a new separate
84  // arena with its own extra TBB worker threads if this function is used
85  // in an inappropriate context (and silently such that you might not notice
86  // the problem quickly).
87 
89  WaitingTaskHolder holder(m_task);
90  m_task->decrement_ref_count();
91  m_task = nullptr;
92  return holder;
93  }
94 } // namespace edm
WaitingTaskWithArenaHolder & operator=(const WaitingTaskWithArenaHolder &iRHS)
#define nullptr
void dependentTaskFailed(std::exception_ptr iPtr)
Called if waited for task failed.
Definition: WaitingTask.h:59
void doneWaiting(std::exception_ptr iExcept)
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
Definition: TBBSession.h:68
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
HLT enums.
std::shared_ptr< tbb::task_arena > m_arena
def move(src, dest)
Definition: eostools.py:511