C++20 jthread stop_token 사용법, 스레드 취소를 어떻게 하나
C++20’s std::jthread automatically calls join() on destruction and carries an internal std::stop_source, so it can hand out a cooperative cancellation signal alongside the thread itself. This note stays narrow: only the auto-join behavior and how to pass and check a stop_token, based on cppreference.
It does not re-explain atomic or RAII fundamentals — only how jthread hooks into stop_token for cancellation.
What sets jthread apart from a plain thread?
Short answer: It joins automatically on destruction and carries a built-in std::stop_source for cooperative cancellation.
A std::thread calls std::terminate if it is destroyed without an explicit join() or detach() call first. Across multiple return paths or exception cases, remembering that call every time is easy to miss.
std::jthread calls join() in its own destructor. The moment the object leaves scope, the running thread is cleaned up safely, removing the class of bugs caused by a forgotten join.
Each jthread instance also holds an internal std::stop_source state from the moment it is created. That state is what lets external code call request_stop() later to ask the thread to cancel.
std::jthread worker([](std::stop_token st) {
while (!st.stop_requested()) {
// do work
}
});
// join() runs automatically when worker goes out of scope
How does a stop_token reach the thread body?
Short answer: Declare std::stop_token as the first parameter of the callable, and jthread injects it automatically at launch.
Cancellation starts outside the thread: calling request_stop() on the jthread object.
To receive that request, the thread’s work routine — a lambda or a function — must accept a std::stop_token as its first argument. jthread passes this token in automatically when it starts the thread.
Inside the loop, poll stop_token.stop_requested() regularly and return once it evaluates to true, so the thread exits cleanly instead of being forced down.
void run(std::stop_token st) {
while (!st.stop_requested()) {
// loop body
}
// clean up, then return
}
std::jthread t(run);
t.request_stop();
If cancellation doesn’t take effect, what should you check?
Short answer: Confirm the loop polls stop_requested() often enough, and that blocking waits use condition_variable_any.
stop_token is cooperative, not a forced kill. If the thread never checks the flag and never returns on its own, the cancellation request is simply ignored.
If the loop contains a long-running heavy step, add checkpoints that call stop_requested() between segments. Sparse checkpoints mean cancellation is only noticed long after the request was made.
Also check whether the thread is sitting in a blocking I/O call or a condition-variable wait. To build an interruptible wait around a stop_token, use std::condition_variable_any instead of the plain std::condition_variable.
| Check | What to verify |
|---|---|
| Poll frequency | Does the loop call stop_requested() often enough? |
| Blocking wait | Is the wait built on condition_variable_any so it can be interrupted? |
| Cancellation model | Does the thread return on its own instead of expecting a forced kill? |
For an immediate reaction, registering a std::stop_callback runs a callback right when the stop request is made.