BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslstl_stoptoken

Detailed Description

Outline

Purpose

Provide an allocator-aware standard-compliant stop_source type.

Classes

Canonical header: bsl_stop_token.h

Description

This component defines the bsl::stop_callback, bsl::stop_source, and bsl::stop_token classes, which provide a thread-safe facility for requesting a cancellation (known as "making a stop request" in the standard), observing cancellation requests, and registering callbacks to be invoked when a cancellation is requested. The interfaces of these classes are identical to those of their std counterparts (available in C++20 and later), except that bsl::stop_callback is allocator-aware and bsl::stop_source has a constructor that accepts an allocator, which is used to allocate the stop state.

Usage

This section illustrates intended use of this component.

Example 1: Condition variable with interruptible wait

bsl::stop_token can be used to implement a condition variable wrapper that allows a wait to be interrupted by a stop. (In C++20, such functionality is available as std::condition_variable_any.) The wrapper must hold a bsl::stop_token object that is used to check whether a stop has been requested, before entering a wait. It is also necessary to ensure that the thread that requests a stop is able to actually wake up any threads that are waiting; for this reason, a bsl::stop_callback must be used to notify the waiting threads automatically when a stop is requested. For simplicity, we will only implement one signature for the wait method.

class InterruptibleCV {
private:
std::condition_variable d_condvar;
public:
void notify_one()
{
d_condvar.notify_one();
}
void notify_all()
{
d_condvar.notify_all();
}
template <class t_PREDICATE>
void wait(std::unique_lock<std::mutex>& lock,
t_PREDICATE pred,
bsl::stop_token stopToken)
{
auto cb = [this] { notify_all(); };
bsl::stop_callback<decltype(cb)> stopCb(stopToken, cb);
while (!stopToken.stop_requested()) {
if (pred()) {
return;
}
d_condvar.wait(lock);
}
}
};
Definition bslstl_stoptoken.h:698
Definition bslstl_stoptoken.h:427
BSLA_NODISCARD bool stop_requested() const BSLS_KEYWORD_NOEXCEPT

The bsl::stop_token object passed to InterruptibleCV::wait will reflect that a stop has been requested only after request_stop is called on a bsl::stop_source object from which the bsl::stop_token was derived (or a copy of that bsl::stop_source).

In the UsageExample class below, the child thread will wait until the value of d_counter is at least 50. However, because the main thread requests a stop after setting d_counter to 10, the child thread wakes up.

struct UsageExample {
std::condition_variable d_startCv;
InterruptibleCV d_stopCv;
std::mutex d_mutex;
long long d_counter;
bool d_ready;
void threadFunc(bsl::stop_token stopToken)
{
std::unique_lock<std::mutex> lg(d_mutex);
d_ready = true;
lg.unlock();
d_startCv.notify_one();
lg.lock();
d_stopCv.wait(lg, [this] { return d_counter >= 50; },
std::move(stopToken));
assert(d_counter >= 10 && d_counter < 50);
}
UsageExample()
: d_counter(0)
, d_ready(false)
{
bsl::stop_source stopSource;
std::thread t(&UsageExample::threadFunc,
this,
stopSource.get_token());
std::unique_lock<std::mutex> lg(d_mutex);
d_startCv.wait(lg, [this] { return d_ready; });
lg.unlock();
for (int i = 0; i < 10; i++) {
lg.lock();
++d_counter;
lg.unlock();
}
assert(stopSource.request_stop());
t.join();
}
};
Definition bslstl_stoptoken.h:556
bool request_stop() BSLS_KEYWORD_NOEXCEPT
BSLA_NODISCARD stop_token get_token() const BSLS_KEYWORD_NOEXCEPT

Due to the levelization of this component, the example above uses the C++11 standard library instead of bslmt::Mutex and similar components, and will therefore compile only in C++11 and higher. However, a similar example can be implemented in C++03 by using bslmt components in a package that is levelized above bslmt.