@@ -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
12281245inline 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
12341251inline 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
21202141template <typename P>
21212142void 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
0 commit comments