BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslstl_stoptoken.h
Go to the documentation of this file.
1/// @file bslstl_stoptoken.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_stoptoken.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_STOPTOKEN
9#define INCLUDED_BSLSTL_STOPTOKEN
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_stoptoken bslstl_stoptoken
15/// @brief Provide an allocator-aware standard-compliant `stop_source` type.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_stoptoken
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_stoptoken-purpose"> Purpose</a>
25/// * <a href="#bslstl_stoptoken-classes"> Classes </a>
26/// * <a href="#bslstl_stoptoken-canonical-header"> Canonical Header </a>
27/// * <a href="#bslstl_stoptoken-description"> Description </a>
28/// * <a href="#bslstl_stoptoken-usage"> Usage </a>
29/// * <a href="#bslstl_stoptoken-example-1-condition-variable-with-interruptible-wait"> Example 1: Condition variable with interruptible wait </a>
30///
31/// # Purpose {#bslstl_stoptoken-purpose}
32/// Provide an allocator-aware standard-compliant @ref stop_source type.
33///
34/// # Classes {#bslstl_stoptoken-classes}
35///
36/// - bsl::nostopstate_t: tag type for creating an empty @ref stop_source
37/// - bsl::stop_callback: callback to be invoked when a stop is requested
38/// - bsl::stop_source: mechanism for requesting stops and invoking callbacks
39/// - bsl::stop_token: mechanism for observing stops and registering callbacks
40///
41/// # Canonical Header {#bslstl_stoptoken-canonical-header}
42/// bsl_stop_token.h
43///
44/// # Description {#bslstl_stoptoken-description}
45/// This component defines the `bsl::stop_callback`,
46/// `bsl::stop_source`, and `bsl::stop_token` classes, which provide a
47/// thread-safe facility for requesting a cancellation (known as "making a stop
48/// request" in the standard), observing cancellation requests, and registering
49/// callbacks to be invoked when a cancellation is requested. The interfaces of
50/// these classes are identical to those of their `std` counterparts (available
51/// in C++20 and later), except that `bsl::stop_callback` is allocator-aware and
52/// `bsl::stop_source` has a constructor that accepts an allocator, which is
53/// used to allocate the stop state.
54///
55/// ## Usage {#bslstl_stoptoken-usage}
56///
57///
58/// This section illustrates intended use of this component.
59///
60/// ### Example 1: Condition variable with interruptible wait {#bslstl_stoptoken-example-1-condition-variable-with-interruptible-wait}
61///
62///
63/// `bsl::stop_token` can be used to implement a condition variable wrapper that
64/// allows a wait to be interrupted by a stop. (In C++20, such functionality is
65/// available as `std::condition_variable_any`.) The wrapper must hold a
66/// `bsl::stop_token` object that is used to check whether a stop has been
67/// requested, before entering a wait. It is also necessary to ensure that the
68/// thread that requests a stop is able to actually wake up any threads that are
69/// waiting; for this reason, a `bsl::stop_callback` must be used to notify the
70/// waiting threads automatically when a stop is requested. For simplicity, we
71/// will only implement one signature for the `wait` method.
72/// @code
73/// class InterruptibleCV {
74/// private:
75/// std::condition_variable d_condvar;
76///
77/// public:
78/// void notify_one()
79/// {
80/// d_condvar.notify_one();
81/// }
82///
83/// void notify_all()
84/// {
85/// d_condvar.notify_all();
86/// }
87///
88/// template <class t_PREDICATE>
89/// void wait(std::unique_lock<std::mutex>& lock,
90/// t_PREDICATE pred,
91/// bsl::stop_token stopToken)
92/// {
93/// auto cb = [this] { notify_all(); };
94///
95/// bsl::stop_callback<decltype(cb)> stopCb(stopToken, cb);
96/// while (!stopToken.stop_requested()) {
97/// if (pred()) {
98/// return;
99/// }
100/// d_condvar.wait(lock);
101/// }
102/// }
103/// };
104/// @endcode
105/// The `bsl::stop_token` object passed to `InterruptibleCV::wait` will reflect
106/// that a stop has been requested only after @ref request_stop is called on a
107/// `bsl::stop_source` object from which the `bsl::stop_token` was derived (or a
108/// copy of that `bsl::stop_source`).
109///
110/// In the `UsageExample` class below, the child thread will wait until the
111/// value of `d_counter` is at least 50. However, because the main thread
112/// requests a stop after setting `d_counter` to 10, the child thread wakes up.
113/// @code
114/// struct UsageExample {
115/// std::condition_variable d_startCv;
116/// InterruptibleCV d_stopCv;
117/// std::mutex d_mutex;
118/// long long d_counter;
119/// bool d_ready;
120///
121/// void threadFunc(bsl::stop_token stopToken)
122/// {
123/// std::unique_lock<std::mutex> lg(d_mutex);
124/// d_ready = true;
125/// lg.unlock();
126/// d_startCv.notify_one();
127///
128/// lg.lock();
129/// d_stopCv.wait(lg, [this] { return d_counter >= 50; },
130/// std::move(stopToken));
131///
132/// assert(d_counter >= 10 && d_counter < 50);
133/// }
134///
135/// UsageExample()
136/// : d_counter(0)
137/// , d_ready(false)
138/// {
139/// bsl::stop_source stopSource;
140///
141/// std::thread t(&UsageExample::threadFunc,
142/// this,
143/// stopSource.get_token());
144///
145/// std::unique_lock<std::mutex> lg(d_mutex);
146/// d_startCv.wait(lg, [this] { return d_ready; });
147/// lg.unlock();
148///
149/// for (int i = 0; i < 10; i++) {
150/// lg.lock();
151/// ++d_counter;
152/// lg.unlock();
153/// }
154///
155/// assert(stopSource.request_stop());
156///
157/// t.join();
158/// }
159/// };
160/// @endcode
161/// Due to the levelization of this component, the example above uses the C++11
162/// standard library instead of `bslmt::Mutex` and similar components, and will
163/// therefore compile only in C++11 and higher. However, a similar example can
164/// be implemented in C++03 by using `bslmt` components in a package that is
165/// levelized above `bslmt`.
166/// @}
167/** @} */
168/** @} */
169
170/** @addtogroup bsl
171 * @{
172 */
173/** @addtogroup bslstl
174 * @{
175 */
176/** @addtogroup bslstl_stoptoken
177 * @{
178 */
179
180#include <bsla_nodiscard.h>
181
182#include <bslma_bslallocator.h>
186
187#include <bslmf_movableref.h>
189#include <bslmf_util.h> // 'forward(V)' for C++03
190
191#include <bsls_atomic.h>
193#include <bsls_keyword.h>
194#include <bsls_objectbuffer.h>
195#include <bsls_util.h> // 'forward<T>(V)' for C++11
196
197#include <bslstl_sharedptr.h>
198#include <bslstl_stopstate.h>
199#include <bsls_exceptionutil.h>
200
201#include <utility>
202
203namespace bsl {
204template <class t_CALLBACK> class stop_callback;
205} // close namespace bsl
206
207
208namespace bslstl {
209
210 // ==========================
211 // class StopCallback_NoAlloc
212 // ==========================
213
214/// This component-private empty class is used as a dummy "allocator" when
215/// `bsl::stop_callback` wraps a non-allocator-aware type.
216///
217/// See @ref bslstl_stoptoken
219
220 private:
221 // FRIENDS
222 template <class t_CALLBACK>
223 friend class bsl::stop_callback;
224
225 // PRIVATE CREATORS
226
227 /// This private constructor declaration prevents `StopCallback_NoAlloc`
228 /// from being an aggregate.
230};
231
232 // ================================
233 // struct StopToken_RefCountedState
234 // ================================
235
236/// This component-private struct adds a reference count to the internal
237/// `StopState` class. This reference count represents the number of
238/// `bsl::stop_source` objects that refer to the stop state (NOT the total
239/// number of objects that refer to the stop state).
240///
241/// Implementation note: The reference count has been kept outside the
242/// `StopState` object in order to enable `StopState` to potentially be
243/// reused to implement `in_place_stop_source` (from WG21 proposal P2300R7)
244/// without the overhead from the reference count.
246
247 // PUBLIC DATA
248
249 /// The number of `bsl::stop_source` objects that refer to this stop
250 /// state.
252};
253
254 // ==================================
255 // class StopCallback_CallbackStorage
256 // ==================================
257
258/// The primary class template stores an object of non-reference type given
259/// by the template parameter `t_CALLBACK`. (That is, the primary template
260/// provides the implementation only when `t_IS_REFERENCE` is `false`.)
261///
262/// See @ref bslstl_stoptoken
263template <class t_CALLBACK,
264 bool t_IS_REFERENCE = bsl::is_reference<t_CALLBACK>::value>
266
267 private:
268 // DATA
270
271 // PRIVATE CLASS METHODS
272
273 /// Return a pointer derived from the specified `allocator` or the
274 /// specified `noAlloc` suitable for being passed to
275 /// `bslma::ConstructionUtil::construct`, i.e., `allocator.mechanism()`
276 /// or a null pointer, respectively.
277 static bslma::Allocator *mechanism(const bsl::allocator<char>& allocator);
278 static void *mechanism(const StopCallback_NoAlloc& noAlloc);
279
280 public:
281 // TYPES
282 typedef typename bsl::conditional<
283 BloombergLP::bslma::UsesBslmaAllocator<t_CALLBACK>::value,
286
287 // CREATORS
288
289 /// Initialize the stored callback by forwarding the specified `arg` to
290 /// the constructor of `t_CALLBACK`; the specified `allocator` is used
291 /// to supply memory if `t_CALLBACK` is allocator-aware (and ignored
292 /// otherwise).
293 template <class t_ARG>
295 const allocator_type& allocator,
297 template <class t_ARG>
299 const allocator_type& allocator,
300 t_ARG& arg);
301
302 /// Destroy this object.
304
305 // MANIPULATORS
306
307 /// Return a reference to the stored callback.
308 t_CALLBACK& callback();
309
310 // ACCESSORS
311
312 /// Return a `const` reference to the stored callback.
313 const t_CALLBACK& callback() const;
314};
315
316/// This partial specialization stores a reference to a callback.
317template <class t_CALLBACK>
318class StopCallback_CallbackStorage<t_CALLBACK, true> {
319
320 private:
321 // DATA
322 t_CALLBACK d_callback;
323
324 public:
325 // TYPES
327
328 // CREATORS
329
330 /// Initialize the stored reference by forwarding the specified `arg`.
331 ///
332 /// \note Note that the allocator argument is ignored because references are
333 /// never allocator-aware.
334 template <class t_ARG>
337 template <class t_ARG>
339 t_ARG& arg);
340
341 // ACCESSORS
342
343 /// Return an lvalue referring to the callback.
345};
346
347 // =======================
348 // class StopCallback_Node
349 // =======================
350
351/// This component-private class is used to implement `bsl::stop_callback`.
352/// It overrides the virtual `invoke` method of
353/// `bslstl::StopStateCallbackNode`, which allows it to be registered and
354/// invoked by `bslstl::StopState`.
355template <class t_CALLBACK>
357 public StopStateCallbackNode {
358
359 private:
360 // PRIVATE MANIPULATORS
361
362 /// Invoke the stored callback.
364
365 public:
366 // CREATORS
367
368 /// Create a `StopCallback_Node` object whose stored callable is
369 /// constructed by forwarding from the specified `arg`; the specified
370 /// `allocator` is used to supply memory if `t_CALLBACK` is
371 /// allocator-aware (and ignored otherwise).
372 template <class t_ALLOC, class t_ARG>
373 StopCallback_Node(const t_ALLOC& allocator,
375 template <class t_ALLOC, class t_ARG>
376 StopCallback_Node(const t_ALLOC& allocator,
377 t_ARG& arg);
378};
379} // close package namespace
380
381
382namespace bsl {
383class stop_source;
384
385 // ====================
386 // struct nostopstate_t
387 // ====================
388
389/// An object of this empty struct can be passed to the constructor of
390/// @ref stop_source to create a @ref stop_source object that does not refer to
391/// any stop state.
392///
393/// See @ref bslstl_stoptoken
395
396 // CREATORS
397
398 /// Create a `nostopstate_t` value.
400};
401
402 // --------------------
403 // struct nostopstate_t
404 // --------------------
405
406// CREATORS
407
408/// This `constexpr` function must be defined before it can be used to
409/// initialize the `constexpr` variable `nostopstate`, below.
410inline
414
415/// Value of type `nostopstate_t` used as an argument to functions that take
416/// a `nostopstate_t` argument.
417#if defined(BSLS_COMPILERFEATURES_SUPPORT_INLINE_VARIABLES)
418inline constexpr nostopstate_t nostopstate{};
419#else
420extern const nostopstate_t nostopstate;
421#endif
422
423 // ================
424 // class stop_token
425 // ================
426
427/// This class is a mechanism for observing cancellation requests. An
428/// object of this class either has (possibly shared) ownership of a stop
429/// state and can be used to observe whether a cancellation request has been
430/// made on that stop state, or does not own a stop state. A @ref stop_token
431/// cannot be used to make a cancellation request.
432///
433/// See @ref bslstl_stoptoken
435
436 public:
437 // PUBLIC TYPES
438#ifdef BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES
439 template <class t_CALLBACK>
440 using callback_type = stop_callback<t_CALLBACK>;
441#endif
442
443 private:
444 // PRIVATE TYPES
445 typedef BloombergLP::bslstl::StopToken_RefCountedState RefCountedState;
446 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
447
448 // DATA
449
450 // pointer to the stop state owned by this object, if any
452
453 // FRIENDS
454 friend class stop_source;
455
456 template <class t_CALLBACK>
457 friend class stop_callback;
458
459 /// Return `true` if the specified `lhs` and `rhs` refer to the same
460 /// stop state, or if neither refers to a stop state; `false` otherwise.
461 /// Implementation note: this function is required by the standard to be
462 /// a hidden friend ([hidden.friends], [stoptoken.general]).
464 const stop_token& lhs,
466 {
467 return lhs.d_state_p == rhs.d_state_p;
468 }
469
470#ifndef BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
471 /// Return `true` if the specified `lhs` and `rhs` refer to different
472 /// stop states, or if only one refers to a stop state; `false`
473 /// otherwise.
475 const stop_token& lhs,
477 {
478 return lhs.d_state_p != rhs.d_state_p;
479 }
480#endif
481
482 /// Set `lhs` to refer to the stop state (or lack thereof) that `rhs`
483 /// referred to, and vice versa. Implementation note: this function is
484 /// required by the standard to be a hidden friend ([hidden.friends],
485 /// [stoptoken.general]).
487 {
488 lhs.d_state_p.swap(rhs.d_state_p);
489 }
490
491 // PRIVATE CREATORS
492
493 /// Create a @ref stop_token object that refers to the stop state that the
494 /// specified `state` points to (if any).
496
497 public:
498 // CREATORS
499
500 /// Create a @ref stop_token object that does not refer to a stop state.
502
503 /// Create a @ref stop_token object that refers to the same stop state (or
504 /// lack thereof) as the specified `original` object.
506
507 /// Create a @ref stop_token object that refers to the same stop state (or
508 /// lack) thereof as the specified `original` object, and reset
509 /// `original` to not refer to a stop state.
510 stop_token(BloombergLP::bslmf::MovableRef<stop_token> original)
512
513 /// Destroy this object.
514 ~stop_token();
515
516 // MANIPULATORS
517
518 /// Set this object to refer to the same stop state (or lack thereof) as
519 /// the specified `other` object.
520 stop_token& operator=(const stop_token& other) BSLS_KEYWORD_NOEXCEPT;
521
522 /// Set this object to refer to the stop state (or lack thereof) that
523 /// the specified `other` object refers to, and reset `other` to not
524 /// refer to a stop state.
525 stop_token& operator=(BloombergLP::bslmf::MovableRef<stop_token> other)
527
528 /// Set `*this` to refer to the stop state (or lack thereof) that the
529 /// specified `other` referred to, and vice versa. Equivalent to
530 /// `swap(*this, other)`.
532
533 // ACCESSORS
534
535 /// Return `true` if `*this` refers to a stop state, and either a stop
536 /// was already requested on that stop state or there is at least one
537 /// @ref stop_source object that refers to that stop state (implying that a
538 /// stop could still be requested using the @ref request_stop function),
539 /// and `false` otherwise. A call to @ref stop_possible that is
540 /// potentially concurrent with a call to @ref stop_requested or
541 /// @ref stop_possible does not cause a data race.
543
544 /// Return `true` if `*this` refers to a stop state on which
545 /// @ref request_stop has been called, and `false` otherwise. If this
546 /// function returns `true`, then the successful call to @ref request_stop
547 /// synchronizes with this call. A call to @ref stop_requested that is
548 /// potentially concurrent with a call to @ref stop_requested or
549 /// @ref stop_possible does not cause a data race.
551};
552
553 // =================
554 // class stop_source
555 // =================
556
557/// This class is a mechanism for making and observing cancellation
558/// requests. An object of this class may have (possibly shared) ownership
559/// of a stop state, in which case it can be used to make a cancellation
560/// request or observe whether a cancellation request has been made on the
561/// owned stop state; it is also possible for a @ref stop_source object to not
562/// own a stop state. Due to its shared ownership semantics, it is safe to
563/// pass a copy of a @ref stop_source object to a callback that might outlive
564/// the original @ref stop_source object; however, a callback that should only
565/// be able to observe a cancellation request, without being able to
566/// request cancellation itself, should instead be passed a @ref stop_token ,
567/// which can be created by calling `stop_source::get_token`.
568///
569/// See @ref bslstl_stoptoken
571
572 private:
573 // PRIVATE TYPES
574 typedef BloombergLP::bslstl::StopToken_RefCountedState RefCountedState;
575 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
576
577 // DATA
578
579 // pointer to the stop state owned by this object, if any
581
582 // FRIENDS
583
584 /// Return `true` if the specified `lhs` and `rhs` refer to the same
585 /// stop state, or if neither refers to a stop state; `false` otherwise.
586 /// Implementation note: this function is required by the standard to be
587 /// a hidden friend ([hidden.friends], [stopsource.general]).
589 const stop_source& lhs,
591 {
592 return lhs.d_state_p == rhs.d_state_p;
593 }
594
595#ifndef BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
596 /// Return `true` if the specified `lhs` and `rhs` refer to different
597 /// stop states, or if only one refers to a stop state; `false`
598 /// otherwise.
600 const stop_source& lhs,
602 {
603 return lhs.d_state_p != rhs.d_state_p;
604 }
605#endif
606
607 /// Set `lhs` to refer to the stop state (or lack thereof) that `rhs`
608 /// referred to before the call, and vice versa. Implementation note:
609 /// this function is required by the standard to be a hidden friend
610 /// ([hidden.friends], [stopsource.general]).
612 {
613 lhs.d_state_p.swap(rhs.d_state_p);
614 }
615
616 public:
617 // CREATORS
618
619 /// Create a @ref stop_source object that refers to a distinct stop state,
620 /// using the currently installed default allocator to supply memory.
622
623 /// Create a @ref stop_source object that does not refer to a stop state
624 /// and, therefore, cannot be used to request a stop.
626
627 /// Create a @ref stop_source object that refers to the same stop state (or
628 /// lack thereof) as the specified 'original.
630
631 /// Create a @ref stop_source object that refers to the stop state (or lack
632 /// thereof) referred to by the specified `original`, and reset
633 /// `original` to not refer to a stop state.
634 stop_source(BloombergLP::bslmf::MovableRef<stop_source> original)
636
637 /// Create a @ref stop_source object that refers to a distinct stop state,
638 /// using the specified `allocator` to supply memory. Note, however,
639 /// that @ref stop_source is not allocator-aware.
641
642 /// Destroy this object.
644
645 // MANIPULATORS
646
647 /// Set this object to refer to the same stop state (or lack thereof) as
648 /// the specified `other` object.
650
651 /// Set this object to refer to the stop state (or lack thereof) that
652 /// the specified `other` object refers to, and reset `other` to not
653 /// refer to a stop state.
654 stop_source& operator=(BloombergLP::bslmf::MovableRef<stop_source> other)
656
657 /// Set `*this` to refer to the stop state (or lack thereof) that the
658 /// specified `other` referred to, and vice versa. Equivalent to
659 /// `swap(*this, other)`.
661
662 /// If `*this` refers to a stop state and that stop state has not had a
663 /// stop requested yet, atomically request a stop on that stop state,
664 /// invoke all registered callbacks in an unspecified order, and finally
665 /// return `true`. Otherwise, return `false`. If this function returns
666 /// `true`, the call synchronizes with any call to @ref stop_requested that
667 /// returns `true`. A call to @ref request_stop that is potentially
668 /// concurrent with a call to @ref stop_requested , @ref stop_possible , or
669 /// @ref request_stop does not cause a data race.
671
672 // ACCESSORS
673
674 /// Return a @ref stop_token that refers to the stop state (or lack
675 /// thereof) that `*this` refers to.
677
678 /// Return `true` if `*this` refers to a stop state, and `false`
679 /// otherwise. A call to @ref stop_possible that is potentially concurrent
680 /// with a call to @ref stop_requested , @ref stop_possible , or @ref request_stop
681 /// does not cause a data race.
683
684 /// Return `true` if `*this` refers to a stop state on which
685 /// @ref request_stop has been called, and `false` otherwise. If this
686 /// function returns `true`, then the successful call to @ref request_stop
687 /// synchronizes with this call. A call to @ref stop_requested that is
688 /// potentially concurrent with a call to @ref stop_requested ,
689 /// @ref stop_possible , or @ref request_stop does not cause a data race.
691};
692
693 // ===================
694 // class stop_callback
695 // ===================
696
697/// This class holds an object or reference of type `t_CALLBACK` and, when
698/// constructed using a @ref stop_token that owns a stop state, schedules the
699/// held object or reference to be executed by the thread that requests
700/// cancellation on that stop state (if any). However, if cancellation was
701/// already requested before the @ref stop_callback was constructed, the
702/// constructor invokes the callback immediately. If there is no stop
703/// state, or @ref request_stop is never called for the stop state, then the
704/// callback is not invoked. @ref stop_callback stores its callback within its
705/// own footprint, and thus never requires memory allocation; however,
706/// `stop_callback<t_CALLBACK>` is an allocator-aware class, if `t_CALLBACK`
707/// is an allocator-aware class, and any supplied allocator will then be
708/// passed to the constructor of `t_CALLBACK`.
709///
710/// See @ref bslstl_stoptoken
711template <class t_CALLBACK>
713
714 private:
715 // PRIVATE TYPES
716 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
717
718 // DATA
719
720 // object that holds the `t_CALLBACK` object or reference and can be a
721 // member of the intrusive linked list maintained by
722 // `bslstl_StopState`
723 BloombergLP::bslstl::StopCallback_Node<t_CALLBACK> d_node;
724
725 // pointer to the stop state on which `d_node` is scheduled to be
726 // invoked, if any
728
729 // PRIVATE MANIPULATORS
730
731 /// Attempt to register the stored callable with the stop state that
732 /// `*this` refers to (if any), and reset `d_state_p` if unsuccessful.
733 void init();
734
735 private:
736 // NOT IMPLEMENTED
739
740 public:
741 // TYPES
742 typedef t_CALLBACK callback_type;
743
744 /// The allocator type is `bsl::allocator<char>` if `t_CALLBACK` is
745 /// allocator-aware, and an empty dummy type otherwise.
746 typedef typename BloombergLP::bslstl::StopCallback_Node<
747 t_CALLBACK>::allocator_type allocator_type;
748
749 // CREATORS
750
751 /// Create a @ref stop_callback object whose stored callable is constructed
752 /// by forwarding from the specified `arg`; if `t_CALLBACK` is
753 /// allocator-aware, the optionally specified `alloc` will be used to
754 /// supply memory instead of the default allocator (otherwise, `alloc`
755 /// is ignored). If the specified `token` refers to a stop state on
756 /// which a stop has been requested, invoke the callback before
757 /// returning; otherwise, if `token` refers to a stop state, associate
758 /// `*this` with that stop state and register the callback with that
759 /// stop state. Unlike the constructors of `std::stop_callback`, these
760 /// constructors do not currently have a `noexcept` specification.
761 ///
762 /// \note Note that if `token` is an rvalue reference, it is unspecified whether
763 /// this function moves from `token`.
764 template <class t_ARG>
765 explicit stop_callback(
766 const stop_token& token,
768 const allocator_type& alloc = allocator_type());
769 template <class t_ARG>
770 explicit stop_callback(
771 BloombergLP::bslmf::MovableRef<stop_token> token,
773 const allocator_type& alloc = allocator_type());
774 template <class t_ARG>
775 explicit stop_callback(
776 const stop_token& token,
777 t_ARG& arg,
778 const allocator_type& alloc = allocator_type());
779 template <class t_ARG>
780 explicit stop_callback(
781 BloombergLP::bslmf::MovableRef<stop_token> token,
782 t_ARG& arg,
783 const allocator_type& alloc = allocator_type());
784
785 /// Destroy this object. If `*this` refers to a stop state and the
786 /// stored callback is registered with the stop state but has not yet
787 /// begun execution, deregister the callback from that stop state.
788 /// Otherwise, if the callback is executing on a thread other than the
789 /// thread invoking the destructor, the completion of the callback
790 /// strongly happens before the destructor returns.
792
793 // ACCESSORS
794
795 /// If `t_CALLBACK` is allocator-aware, return the allocator used to
796 /// construct this object; otherwise, the return type is `void` and the
797 /// definition of this function is ill-formed.
798 allocator_type get_allocator() const;
799};
800
801#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
802// CLASS TEMPLATE DEDUCTION GUIDES
803template <class t_CALLBACK>
805#endif
806} // close namespace bsl
807
808
809namespace bslma {
810template <class t_CALLBACK>
811struct UsesBslmaAllocator<bsl::stop_callback<t_CALLBACK> >
812: UsesBslmaAllocator<t_CALLBACK> {
813};
814} // close namespace bslma
815
816
817// ============================================================================
818// INLINE DEFINITIONS
819// ============================================================================
820
821
822namespace bslstl {
823
824 // --------------------------
825 // class StopCallback_NoAlloc
826 // --------------------------
827
828inline StopCallback_NoAlloc::StopCallback_NoAlloc()
829{
830}
831
832 // -----------------------------------------------------
833 // class StopCallback_CallbackStorage<t_CALLBACK, false>
834 // -----------------------------------------------------
835
836
837template <class t_CALLBACK, bool t_IS_REFERENCE>
839StopCallback_CallbackStorage<t_CALLBACK, t_IS_REFERENCE>::mechanism(
840 const bsl::allocator<char>& allocator)
841{
842 return allocator.mechanism();
843}
844
845template <class t_CALLBACK, bool t_IS_REFERENCE>
846void *StopCallback_CallbackStorage<t_CALLBACK, t_IS_REFERENCE>::mechanism(
847 const StopCallback_NoAlloc&)
848{
849 return 0;
850}
851
852template <class t_CALLBACK, bool t_IS_REFERENCE>
853template <class t_ARG>
856 const allocator_type& allocator,
858{
859 BloombergLP::bslma::ConstructionUtil::construct(
860 d_buf.address(),
861 mechanism(allocator),
863}
864
865template <class t_CALLBACK, bool t_IS_REFERENCE>
866template <class t_ARG>
868 StopCallback_CallbackStorage(const allocator_type& allocator, t_ARG& arg)
869{
870 BloombergLP::bslma::ConstructionUtil::construct(d_buf.address(),
871 mechanism(allocator),
872 arg);
873}
874
875template <class t_CALLBACK, bool t_IS_REFERENCE>
877 t_IS_REFERENCE>::~StopCallback_CallbackStorage()
878{
879 BloombergLP::bslma::DestructionUtil::destroy(d_buf.address());
880}
881
882template <class t_CALLBACK, bool t_IS_REFERENCE>
883t_CALLBACK&
888
889template <class t_CALLBACK, bool t_IS_REFERENCE>
890const t_CALLBACK&
895
896 // ----------------------------------------------------
897 // class StopCallback_CallbackStorage<t_CALLBACK, true>
898 // ----------------------------------------------------
899
900template <class t_CALLBACK>
901template <class t_ARG>
908
909template <class t_CALLBACK>
910template <class t_ARG>
917
918template <class t_CALLBACK>
921{
922 return d_callback;
923}
924
925 // -----------------------------------
926 // class StopCallback_Node<t_CALLBACK>
927 // -----------------------------------
928
929template <class t_CALLBACK>
931{
932 // We cannot use 'BSLS_COMPILERFEATURES_FORWARD' here because it will add
933 // 'const' in C++03.
934#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
935 std::forward<t_CALLBACK>(
937#else
939#endif
940}
941
942template <class t_CALLBACK>
943template <class t_ALLOC, class t_ARG>
945 const t_ALLOC& allocator,
947: StopCallback_CallbackStorage<t_CALLBACK>(allocator,
949 arg))
950{
951}
952
953template <class t_CALLBACK>
954template <class t_ALLOC, class t_ARG>
956 t_ARG& arg)
957: StopCallback_CallbackStorage<t_CALLBACK>(allocator, arg)
958{
959}
960} // close package namespace
961
962
963 // ----------------
964 // class stop_token
965 // ----------------
966
967namespace bsl {
968// PRIVATE CREATORS
969inline
971: d_state_p(MoveUtil::move(state))
972{
973}
974
975// CREATORS
976inline
977stop_token::stop_token() BSLS_KEYWORD_NOEXCEPT
978: d_state_p()
979{
980}
981
982inline
983stop_token::stop_token(const stop_token& original) BSLS_KEYWORD_NOEXCEPT
984: d_state_p(original.d_state_p)
985{
986}
987
988inline
989stop_token::stop_token(BloombergLP::bslmf::MovableRef<stop_token> original)
991: d_state_p(MoveUtil::move(MoveUtil::access(original).d_state_p))
992{
993}
994
995inline
996stop_token::~stop_token()
997{
998}
999
1000// MANIPULATORS
1001inline
1002stop_token& stop_token::operator=(
1003 const stop_token& other) BSLS_KEYWORD_NOEXCEPT
1004{
1005 d_state_p = other.d_state_p;
1006 return *this;
1007}
1008
1009inline
1010stop_token& stop_token::operator=(
1011 BloombergLP::bslmf::MovableRef<stop_token> other) BSLS_KEYWORD_NOEXCEPT
1012{
1013 d_state_p = MoveUtil::move(MoveUtil::access(other).d_state_p);
1014 return *this;
1015}
1016
1017inline
1018void stop_token::swap(stop_token& other) BSLS_KEYWORD_NOEXCEPT
1019{
1020 d_state_p.swap(other.d_state_p);
1021}
1022
1023 // -----------------
1024 // class stop_source
1025 // -----------------
1026
1027// CREATORS
1028inline
1029stop_source::stop_source(nostopstate_t) BSLS_KEYWORD_NOEXCEPT
1030: d_state_p()
1031{
1032}
1033
1034inline
1035stop_source::stop_source(BloombergLP::bslmf::MovableRef<stop_source> original)
1037: d_state_p(MoveUtil::move(MoveUtil::access(original).d_state_p))
1038{
1039}
1040
1041// MANIPULATORS
1042inline
1043void stop_source::swap(stop_source& other) BSLS_KEYWORD_NOEXCEPT
1044{
1045 d_state_p.swap(other.d_state_p);
1046}
1047
1048 // -------------------
1049 // class stop_callback
1050 // -------------------
1051
1052// PRIVATE MANIPULATORS
1053template <class t_CALLBACK>
1055{
1056 if (d_state_p && !d_state_p->enregister(&d_node)) {
1057 d_state_p.reset();
1058 }
1059}
1060
1061// CREATORS
1062template <class t_CALLBACK>
1063template <class t_ARG>
1065 const stop_token& token,
1067 const allocator_type& alloc)
1068: d_node(alloc, BSLS_COMPILERFEATURES_FORWARD(t_ARG, arg))
1069, d_state_p(token.d_state_p)
1070{
1071 init();
1072}
1073
1074template <class t_CALLBACK>
1075template <class t_ARG>
1077 BloombergLP::bslmf::MovableRef<stop_token> token,
1079 const allocator_type& alloc)
1080: d_node(alloc, BSLS_COMPILERFEATURES_FORWARD(t_ARG, arg))
1081, d_state_p(MoveUtil::move(MoveUtil::access(token).d_state_p))
1082{
1083 init();
1084}
1085
1086template <class t_CALLBACK>
1087template <class t_ARG>
1089 t_ARG& arg,
1090 const allocator_type& alloc)
1091: d_node(alloc, arg)
1092, d_state_p(token.d_state_p)
1093{
1094 init();
1095}
1096
1097template <class t_CALLBACK>
1098template <class t_ARG>
1100 BloombergLP::bslmf::MovableRef<stop_token> token,
1101 t_ARG& arg,
1102 const allocator_type& alloc)
1103: d_node(alloc, arg)
1104, d_state_p(MoveUtil::move(MoveUtil::access(token).d_state_p))
1105{
1106 init();
1107}
1108
1109template <class t_CALLBACK>
1111{
1112 if (d_state_p) {
1113 d_state_p->deregister(&d_node);
1114 }
1115}
1116
1117template <class t_CALLBACK>
1120{
1121 return d_node.callback().get_allocator();
1122}
1123} // close namespace bsl
1124#endif // INCLUDED_BSLSTL_STOPTOKEN
1125
1126// ----------------------------------------------------------------------------
1127// Copyright 2023 Bloomberg Finance L.P.
1128//
1129// Licensed under the Apache License, Version 2.0 (the "License");
1130// you may not use this file except in compliance with the License.
1131// You may obtain a copy of the License at
1132//
1133// http://www.apache.org/licenses/LICENSE-2.0
1134//
1135// Unless required by applicable law or agreed to in writing, software
1136// distributed under the License is distributed on an "AS IS" BASIS,
1137// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1138// See the License for the specific language governing permissions and
1139// limitations under the License.
1140// ----------------------------- END-OF-FILE ----------------------------------
1141
1142/** @} */
1143/** @} */
1144/** @} */
Definition bslma_bslallocator.h:588
BloombergLP::bslma::Allocator * mechanism() const
Definition bslma_bslallocator.h:1146
Definition bslstl_sharedptr.h:1838
void swap(shared_ptr &other) BSLS_KEYWORD_NOEXCEPT
Definition bslstl_sharedptr.h:5516
void reset() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_sharedptr.h:5449
Definition bslstl_stoptoken.h:712
t_CALLBACK callback_type
Definition bslstl_stoptoken.h:742
~stop_callback()
Definition bslstl_stoptoken.h:1110
BloombergLP::bslstl::StopCallback_Node< t_CALLBACK >::allocator_type allocator_type
Definition bslstl_stoptoken.h:747
allocator_type get_allocator() const
Definition bslstl_stoptoken.h:1119
Definition bslstl_stoptoken.h:570
friend void swap(stop_source &lhs, stop_source &rhs) BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stoptoken.h:611
~stop_source()
Destroy this object.
BSLA_NODISCARD friend bool operator!=(const stop_source &lhs, const stop_source &rhs) BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stoptoken.h:599
stop_source & operator=(BloombergLP::bslmf::MovableRef< stop_source > other) BSLS_KEYWORD_NOEXCEPT
stop_source(bsl::allocator< char > allocator)
stop_source(const stop_source &original) BSLS_KEYWORD_NOEXCEPT
bool request_stop() BSLS_KEYWORD_NOEXCEPT
stop_source & operator=(const stop_source &other) BSLS_KEYWORD_NOEXCEPT
BSLA_NODISCARD friend bool operator==(const stop_source &lhs, const stop_source &rhs) BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stoptoken.h:588
Definition bslstl_stoptoken.h:434
BSLA_NODISCARD friend bool operator==(const stop_token &lhs, const stop_token &rhs) BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stoptoken.h:463
BSLA_NODISCARD friend bool operator!=(const stop_token &lhs, const stop_token &rhs) BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stoptoken.h:474
friend class stop_source
Definition bslstl_stoptoken.h:454
friend class stop_callback
Definition bslstl_stoptoken.h:457
stop_token & operator=(const stop_token &other) BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stoptoken.h:1002
friend void swap(stop_token &lhs, stop_token &rhs) BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stoptoken.h:486
stop_token() BSLS_KEYWORD_NOEXCEPT
Create a stop_token object that does not refer to a stop state.
Definition bslstl_stoptoken.h:977
BSLA_NODISCARD bool stop_possible() const BSLS_KEYWORD_NOEXCEPT
BSLA_NODISCARD bool stop_requested() const BSLS_KEYWORD_NOEXCEPT
Definition bslma_allocator.h:545
Definition bsls_atomic.h:1205
StopCallback_NoAlloc allocator_type
Definition bslstl_stoptoken.h:326
Definition bslstl_stoptoken.h:265
~StopCallback_CallbackStorage()
Destroy this object.
Definition bslstl_stoptoken.h:877
bsl::conditional< BloombergLP::bslma::UsesBslmaAllocator< t_CALLBACK >::value, bsl::allocator< char >, StopCallback_NoAlloc >::type allocator_type
Definition bslstl_stoptoken.h:285
t_CALLBACK & callback()
Return a reference to the stored callback.
Definition bslstl_stoptoken.h:884
StopCallback_CallbackStorage(const allocator_type &allocator, BSLS_COMPILERFEATURES_FORWARD_REF(t_ARG) arg)
Definition bslstl_stoptoken.h:855
Definition bslstl_stoptoken.h:218
Definition bslstl_stoptoken.h:357
StopCallback_Node(const t_ALLOC &allocator, BSLS_COMPILERFEATURES_FORWARD_REF(t_ARG) arg)
Definition bslstl_stoptoken.h:944
Definition bslstl_stopstate.h:100
Definition bslstl_stopstate.h:121
#define BSLA_NODISCARD
Definition bsla_nodiscard.h:320
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2343
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2349
#define BSLS_NOTHROW_SPEC
Definition bsls_exceptionutil.h:386
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_CONSTEXPR
Definition bsls_keyword.h:624
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:651
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:674
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:695
Definition bdlat_valuetypefunctions.h:939
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
const nostopstate_t nostopstate
ALLOCATOR & lhs
Definition bslstl_string.h:3917
Definition baljsn_encoder_testtypes.h:76
Definition bdlbb_blob.h:579
Definition bslstl_algorithm.h:84
Definition bslmf_conditional.h:123
Definition bslmf_integralconstant.h:261
Definition bslmf_isreference.h:137
Definition bslstl_stoptoken.h:394
BSLS_KEYWORD_CONSTEXPR nostopstate_t() BSLS_KEYWORD_NOEXCEPT
Create a nostopstate_t value.
Definition bslstl_stoptoken.h:411
t_TYPE type
This typedef is an alias to the (template parameter) t_TYPE.
Definition bslmf_removereference.h:156
Definition bslma_usesbslmaallocator.h:344
Definition bslstl_stoptoken.h:245
bsls::AtomicUint64 d_stopSourceCount
Definition bslstl_stoptoken.h:251
Definition bsls_objectbuffer.h:277
TYPE * address()
Definition bsls_objectbuffer.h:335
TYPE & object()
Definition bsls_objectbuffer.h:352