-
Notifications
You must be signed in to change notification settings - Fork 37
/
Copy pathWaitingTaskHolder.h
122 lines (102 loc) · 3.44 KB
/
WaitingTaskHolder.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#ifndef FWCore_Concurrency_WaitingTaskHolder_h
#define FWCore_Concurrency_WaitingTaskHolder_h
// -*- C++ -*-
//
// Package: FWCore/Concurrency
// Class : WaitingTaskHolder
//
/**\class WaitingTaskHolder WaitingTaskHolder.h "WaitingTaskHolder.h"
Description: [one line class summary]
Usage:
<usage>
*/
//
// Original Author: FWCore
// Created: Fri, 18 Nov 2016 20:30:42 GMT
//
// system include files
#include <cassert>
#include <tbb/task_group.h>
// user include files
#include "Framework/WaitingTask.h"
// forward declarations
namespace edm {
class WaitingTaskHolder {
public:
friend class WaitingTaskList;
friend class WaitingTaskWithArenaHolder;
WaitingTaskHolder() : m_task(nullptr), m_group(nullptr) {}
explicit WaitingTaskHolder(tbb::task_group& iGroup, edm::WaitingTask* iTask) : m_task(iTask), m_group(&iGroup) {
m_task->increment_ref_count();
}
~WaitingTaskHolder() {
if (m_task) {
doneWaiting(std::exception_ptr{});
}
}
WaitingTaskHolder(const WaitingTaskHolder& iHolder) : m_task(iHolder.m_task), m_group(iHolder.m_group) {
m_task->increment_ref_count();
}
WaitingTaskHolder(WaitingTaskHolder&& iOther) : m_task(iOther.m_task), m_group(iOther.m_group) {
iOther.m_task = nullptr;
}
WaitingTaskHolder& operator=(const WaitingTaskHolder& iRHS) {
WaitingTaskHolder tmp(iRHS);
std::swap(m_task, tmp.m_task);
std::swap(m_group, tmp.m_group);
return *this;
}
WaitingTaskHolder& operator=(WaitingTaskHolder&& iRHS) {
WaitingTaskHolder tmp(std::move(iRHS));
std::swap(m_task, tmp.m_task);
std::swap(m_group, tmp.m_group);
return *this;
}
// ---------- const member functions ---------------------
bool taskHasFailed() const noexcept { return m_task->exceptionPtr() != nullptr; }
bool hasTask() const noexcept { return m_task != nullptr; }
/** since tbb::task_group is thread safe, we can return it non-const from here since
the object is not really part of the state of the holder
*/
tbb::task_group* group() const noexcept { return m_group; }
// ---------- static member functions --------------------
// ---------- member functions ---------------------------
/** Use in the case where you need to inform the parent task of a
failure before some other child task which may be run later reports
a different, but related failure. You must later call doneWaiting
in the same thread passing the same exceptoin.
*/
void presetTaskAsFailed(std::exception_ptr iExcept) {
if (iExcept) {
m_task->dependentTaskFailed(iExcept);
}
}
void doneWaiting(std::exception_ptr iExcept) {
if (iExcept) {
m_task->dependentTaskFailed(iExcept);
}
//task_group::run can run the task before we finish
// doneWaiting and some other thread might
// try to reuse this object. Resetting
// before spawn avoids problems
auto task = m_task;
m_task = nullptr;
if (0 == task->decrement_ref_count()) {
m_group->run([task]() {
TaskSentry s{task};
task->execute();
});
}
}
private:
WaitingTask* release_no_decrement() noexcept {
auto t = m_task;
m_task = nullptr;
return t;
}
// ---------- member data --------------------------------
WaitingTask* m_task;
tbb::task_group* m_group;
};
} // namespace edm
#endif