Skip to content

Commit 6bc05be

Browse files
author
Ibraim Ganiev
committed
Switch this_worker to mechanism that does not depend on DLL boundaries
1 parent 234de7b commit 6bc05be

File tree

3 files changed

+38
-24
lines changed

3 files changed

+38
-24
lines changed

taskflow/core/async.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@ namespace tf {
1313

1414
// Procedure: _schedule_async_task
1515
TF_FORCE_INLINE void Executor::_schedule_async_task(Node* node) {
16-
(pt::this_worker) ? _schedule(*pt::this_worker, node) : _schedule(node);
16+
auto w = this_worker();
17+
if(w) {
18+
_schedule(*w, node);
19+
}
20+
else{
21+
_schedule(node);
22+
}
1723
}
1824

1925
// Procedure: _tear_down_async

taskflow/core/executor.hpp

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,16 @@ class Executor {
542542
@endcode
543543
*/
544544
size_t num_taskflows() const;
545+
546+
/**
547+
@brief queries pointer to the current worker if it belongs to this executor, otherwise returns nullptr
548+
549+
@code{.cpp}
550+
auto w = executor.this_worker();
551+
assert(w == nullptr || w->executor() == &executor);
552+
@endcode
553+
*/
554+
Worker* this_worker();
545555

546556
/**
547557
@brief queries the id of the caller thread within this executor
@@ -1063,6 +1073,8 @@ class Executor {
10631073

10641074
std::shared_ptr<WorkerInterface> _worker_interface;
10651075
std::unordered_set<std::shared_ptr<ObserverInterface>> _observers;
1076+
std::unordered_map<std::thread::id, size_t> _wids;
1077+
10661078

10671079
void _shutdown();
10681080
void _observer_prologue(Worker&, Node*);
@@ -1224,23 +1236,31 @@ inline size_t Executor::num_taskflows() const {
12241236
return _taskflows.size();
12251237
}
12261238

1239+
inline Worker* Executor::this_worker() {
1240+
auto itr = _wids.find(std::this_thread::get_id());
1241+
return itr == _wids.end() ? nullptr : &_workers[itr->second];
1242+
}
1243+
12271244
// Function: this_worker_id
12281245
inline int Executor::this_worker_id() const {
1229-
auto w = pt::this_worker;
1230-
return (w && w->_executor == this) ? static_cast<int>(w->_id) : -1;
1246+
auto i = _wids.find(std::this_thread::get_id());
1247+
return i == _wids.end() ? -1 : static_cast<int>(_workers[i->second]._id);
12311248
}
12321249

12331250
// Procedure: _spawn
12341251
inline void Executor::_spawn(size_t N) {
1235-
1252+
std::mutex mutex;
12361253
for(size_t id=0; id<N; ++id) {
12371254
_workers[id]._id = id;
12381255
_workers[id]._vtm = id;
12391256
_workers[id]._executor = this;
12401257
_workers[id]._waiter = &_notifier._waiters[id];
12411258
_workers[id]._thread = std::thread([&, &w=_workers[id]] () {
12421259

1243-
pt::this_worker = &w;
1260+
{
1261+
std::scoped_lock lock(mutex);
1262+
_wids[std::this_thread::get_id()] = w._id;
1263+
}
12441264

12451265
// initialize the random engine and seed for work-stealing loop
12461266
w._rdgen.seed(static_cast<std::default_random_engine::result_type>(
@@ -2080,7 +2100,7 @@ tf::Future<void> Executor::run_until(Taskflow& f, P&& p, C&& c) {
20802100
std::lock_guard<std::mutex> lock(f._mutex);
20812101
f._topologies.push(t);
20822102
if(f._topologies.size() == 1) {
2083-
_set_up_topology(pt::this_worker, t.get());
2103+
_set_up_topology(this_worker(), t.get());
20842104
}
20852105
}
20862106

@@ -2108,23 +2128,25 @@ void Executor::corun(T& target) {
21082128

21092129
static_assert(has_graph_v<T>, "target must define a member function 'Graph& graph()'");
21102130

2111-
if(pt::this_worker == nullptr || pt::this_worker->_executor != this) {
2131+
Worker* w = this_worker();
2132+
if(w == nullptr || w->_executor != this) {
21122133
TF_THROW("corun must be called by a worker of the executor");
21132134
}
21142135

21152136
Node anchor;
2116-
_corun_graph(*pt::this_worker, &anchor, target.graph().begin(), target.graph().end());
2137+
_corun_graph(*w, &anchor, target.graph().begin(), target.graph().end());
21172138
}
21182139

21192140
// Function: corun_until
21202141
template <typename P>
21212142
void Executor::corun_until(P&& predicate) {
21222143

2123-
if(pt::this_worker == nullptr || pt::this_worker->_executor != this) {
2144+
Worker* w = this_worker();
2145+
if(w == nullptr || w->_executor != this) {
21242146
TF_THROW("corun_until must be called by a worker of the executor");
21252147
}
21262148

2127-
_corun_until(*pt::this_worker, std::forward<P>(predicate));
2149+
_corun_until(*w, std::forward<P>(predicate));
21282150
}
21292151

21302152
// Procedure: _corun_graph

taskflow/core/worker.hpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -106,20 +106,6 @@ class Worker {
106106
BoundedTaskQueue<Node*> _wsq;
107107
};
108108

109-
110-
// ----------------------------------------------------------------------------
111-
// Per-thread
112-
// ----------------------------------------------------------------------------
113-
114-
namespace pt {
115-
116-
/**
117-
@private
118-
*/
119-
inline thread_local Worker* this_worker {nullptr};
120-
121-
}
122-
123109
// ----------------------------------------------------------------------------
124110
// Class Definition: WorkerView
125111
// ----------------------------------------------------------------------------

0 commit comments

Comments
 (0)