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