Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: ce762cf2aadc
Choose a base ref
...
head repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 7d6bff8645fb
Choose a head ref
  • 4 commits
  • 3 files changed
  • 1 contributor

Commits on Nov 22, 2020

  1. Copy the full SHA
    28edd0a View commit details
  2. Copy the full SHA
    dadbb2f View commit details

Commits on Nov 24, 2020

  1. After egg's review.

    pleroy committed Nov 24, 2020
    Copy the full SHA
    961dfcf View commit details
  2. Merge pull request #2792 from pleroy/ThisJThread

    Add support for finding the stop_token for the current thread
    pleroy authored Nov 24, 2020
    Copy the full SHA
    7d6bff8 View commit details
Showing with 64 additions and 1 deletion.
  1. +19 −1 base/jthread.hpp
  2. +19 −0 base/jthread_body.hpp
  3. +26 −0 base/jthread_test.cpp
20 changes: 19 additions & 1 deletion base/jthread.hpp
Original file line number Diff line number Diff line change
@@ -22,14 +22,16 @@ class StopState;
// https://en.cppreference.com/w/cpp/thread/stop_token
class stop_token {
public:
stop_token();

bool stop_requested() const;

private:
explicit stop_token(not_null<StopState*> stop_state);

StopState& get_stop_state() const;

not_null<StopState*> const stop_state_;
StopState* stop_state_;

friend class jthread;
friend class stop_callback;
@@ -101,12 +103,28 @@ class jthread {
std::thread thread_;
};

template<typename Function, typename... Args>
static jthread MakeStoppableThread(Function&& f, Args&&... args);

class this_stoppable_thread {
public:
static stop_token get_stop_token();

private:
static thread_local stop_token stop_token_;

template<typename Function, typename... Args>
friend jthread MakeStoppableThread(Function&& f, Args&&... args);
};

} // namespace internal_jthread

using internal_jthread::MakeStoppableThread;
using internal_jthread::jthread;
using internal_jthread::stop_callback;
using internal_jthread::stop_source;
using internal_jthread::stop_token;
using internal_jthread::this_stoppable_thread;

} // namespace base
} // namespace principia
19 changes: 19 additions & 0 deletions base/jthread_body.hpp
Original file line number Diff line number Diff line change
@@ -65,6 +65,8 @@ inline void StopState::Unregister(not_null<stop_callback*> const callback) {
callbacks_.erase(callback);
}

inline stop_token::stop_token() : stop_state_(nullptr) {}

inline bool stop_token::stop_requested() const {
return stop_state_->stop_requested();
}
@@ -140,6 +142,23 @@ inline stop_token jthread::get_stop_token() const {
return stop_token(stop_state_.get());
}

template<typename Function, typename... Args>
jthread MakeStoppableThread(Function&& f, Args&&... args) {
return jthread(
[f](stop_token const& st, Args&&... args) {
// This assignment happens on the thread of the jthread.
this_stoppable_thread::stop_token_ = st;
f(st, args...);
},
args...);
}

stop_token this_stoppable_thread::get_stop_token() {
return stop_token_;
}

thread_local stop_token this_stoppable_thread::stop_token_;

} // namespace internal_jthread
} // namespace base
} // namespace principia
26 changes: 26 additions & 0 deletions base/jthread_test.cpp
Original file line number Diff line number Diff line change
@@ -116,5 +116,31 @@ TEST(JThreadTest, StopCallback) {
EXPECT_TRUE(callback_after_stop_executed);
}

TEST(JThreadTest, ThisJThread) {
bool observed_stop = false;

auto sleepy_worker = MakeStoppableThread(
[](stop_token /*unused*/, bool* const observed_stop) {
for (int i = 0; i < 10; i++) {
absl::SleepFor(absl::Milliseconds(10));
if (this_stoppable_thread::get_stop_token().stop_requested()) {
std::cout << "Sleepy worker is requested to stop\n";
*observed_stop = true;
return;
}
std::cout << "Sleepy worker goes back to sleep\n";
}
},
&observed_stop);

absl::SleepFor(absl::Milliseconds(30));
std::cout << "Requesting stop of sleepy worker\n";
sleepy_worker.request_stop();
sleepy_worker.join();
EXPECT_TRUE(observed_stop);
}



} // namespace base
} // namespace principia