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),
23  m_group(&iGroup),
24  m_arena(std::make_shared<oneapi::tbb::task_arena>(oneapi::tbb::task_arena::attach())) {
26  }
27 
29  : m_task(iTask.release_no_decrement()),
30  m_group(iTask.group()),
31  m_arena(std::make_shared<oneapi::tbb::task_arena>(oneapi::tbb::task_arena::attach())) {}
32 
34  if (m_task) {
35  doneWaiting(std::exception_ptr{});
36  }
37  }
38 
40  : m_task(iHolder.m_task), m_group(iHolder.m_group), m_arena(iHolder.m_arena) {
41  if (LIKELY(m_task != nullptr)) {
43  }
44  }
45 
47  : m_task(iOther.m_task), m_group(iOther.m_group), m_arena(std::move(iOther.m_arena)) {
48  iOther.m_task = nullptr;
49  }
50 
53  std::swap(m_task, tmp.m_task);
54  std::swap(m_group, tmp.m_group);
55  std::swap(m_arena, tmp.m_arena);
56  return *this;
57  }
58 
61  std::swap(m_task, tmp.m_task);
62  std::swap(m_group, tmp.m_group);
63  std::swap(m_arena, tmp.m_arena);
64  return *this;
65  }
66 
67  // This spawns the task. The arena is needed to get the task spawned
68  // into the correct arena of threads. Use of the arena allows doneWaiting
69  // to be called from a thread outside the arena of threads that will manage
70  // the task. doneWaiting can be called from a non-TBB thread.
71  void WaitingTaskWithArenaHolder::doneWaiting(std::exception_ptr iExcept) {
72  if (iExcept) {
73  m_task->dependentTaskFailed(iExcept);
74  }
75  //enqueue can run the task before we finish
76  // doneWaiting and some other thread might
77  // try to reuse this object. Resetting
78  // before enqueue avoids problems
79  auto task = m_task;
80  m_task = nullptr;
81  if (0 == task->decrement_ref_count()) {
82  // The enqueue call will cause a worker thread to be created in
83  // the arena if there is not one already.
84  m_arena->enqueue([task = task, group = m_group]() {
85  group->run([task]() {
86  TaskSentry s(task);
87  task->execute();
88  });
89  });
90  }
91  }
92 
93  // This next function is useful if you know from the context that
94  // m_arena (which is set when the constructor was executes) is the
95  // same arena in which you want to execute the doneWaiting function.
96  // It allows an optimization which avoids the enqueue step in the
97  // doneWaiting function.
98  //
99  // Be warned though that in general this function cannot be used.
100  // Spawning a task outside the correct arena could create a new separate
101  // arena with its own extra TBB worker threads if this function is used
102  // in an inappropriate context (and silently such that you might not notice
103  // the problem quickly).
104 
106  WaitingTaskHolder holder(*m_group, m_task);
108  m_task = nullptr;
109  return holder;
110  }
111 
112  bool WaitingTaskWithArenaHolder::taskHasFailed() const noexcept { return m_task->exceptionPtr() != nullptr; }
113 
114  bool WaitingTaskWithArenaHolder::hasTask() const noexcept { return m_task != nullptr; }
115 
116 } // namespace edm
WaitingTaskWithArenaHolder & operator=(const WaitingTaskWithArenaHolder &iRHS)
std::exception_ptr const * exceptionPtr() const
Returns exception thrown by dependent task.
Definition: WaitingTask.h:51
#define LIKELY(x)
Definition: Likely.h:20
std::shared_ptr< oneapi::tbb::task_arena > m_arena
void dependentTaskFailed(std::exception_ptr iPtr)
Called if waited for task failed.
Definition: WaitingTask.h:59
void doneWaiting(std::exception_ptr iExcept)
oneapi::tbb::task_group * group() const
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
HLT enums.
unsigned int decrement_ref_count()
Definition: TaskBase.h:42
tmp
align.sh
Definition: createJobs.py:716
def move(src, dest)
Definition: eostools.py:511
void increment_ref_count()
Definition: TaskBase.h:41