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 
13 
14 namespace edm {
15 
17 
18  // Note that the arena will be the one containing the thread
19  // that runs this constructor. This is the arena where you
20  // eventually intend for the task to be spawned.
22  : m_task(iTask), m_arena(std::make_shared<tbb::task_arena>(tbb::task_arena::attach())) {
23  m_task->increment_ref_count();
24  }
25 
27  if (m_task) {
28  doneWaiting(std::exception_ptr{});
29  }
30  }
31 
33  : m_task(iHolder.m_task), m_arena(iHolder.m_arena) {
34  if (LIKELY(m_task != nullptr)) {
35  m_task->increment_ref_count();
36  }
37  }
38 
40  : m_task(iOther.m_task), m_arena(std::move(iOther.m_arena)) {
41  iOther.m_task = nullptr;
42  }
43 
46  std::swap(m_task, tmp.m_task);
48  return *this;
49  }
50 
53  std::swap(m_task, tmp.m_task);
55  return *this;
56  }
57 
58  // This spawns the task. The arena is needed to get the task spawned
59  // into the correct arena of threads. Use of the arena allows doneWaiting
60  // to be called from a thread outside the arena of threads that will manage
61  // the task. doneWaiting can be called from a non-TBB thread.
62  void WaitingTaskWithArenaHolder::doneWaiting(std::exception_ptr iExcept) {
63  if (iExcept) {
64  m_task->dependentTaskFailed(iExcept);
65  }
66  //enqueue can run the task before we finish
67  // doneWaiting and some other thread might
68  // try to reuse this object. Resetting
69  // before enqueue avoids problems
70  auto task = m_task;
71  m_task = nullptr;
72  if (0 == task->decrement_ref_count()) {
73  // The enqueue call will cause a worker thread to be created in
74  // the arena if there is not one already.
75  m_arena->enqueue([task = task]() { tbb::task::spawn(*task); });
76  }
77  }
78 
79  // This next function is useful if you know from the context that
80  // m_arena (which is set when the constructor was executes) is the
81  // same arena in which you want to execute the doneWaiting function.
82  // It allows an optimization which avoids the enqueue step in the
83  // doneWaiting function.
84  //
85  // Be warned though that in general this function cannot be used.
86  // Spawning a task outside the correct arena could create a new separate
87  // arena with its own extra TBB worker threads if this function is used
88  // in an inappropriate context (and silently such that you might not notice
89  // the problem quickly).
90 
92  WaitingTaskHolder holder(m_task);
93  m_task->decrement_ref_count();
94  m_task = nullptr;
95  return holder;
96  }
97 } // namespace edm
WaitingTaskWithArenaHolder & operator=(const WaitingTaskWithArenaHolder &iRHS)
#define nullptr
#define LIKELY(x)
Definition: Likely.h:20
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
HLT enums.
tmp
align.sh
Definition: createJobs.py:716
std::shared_ptr< tbb::task_arena > m_arena
def move(src, dest)
Definition: eostools.py:511