stop_callback.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // -*- C++ -*-
  2. //===----------------------------------------------------------------------===//
  3. //
  4. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  5. // See https://llvm.org/LICENSE.txt for license information.
  6. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #ifndef _LIBCPP___STOP_TOKEN_STOP_CALLBACK_H
  10. #define _LIBCPP___STOP_TOKEN_STOP_CALLBACK_H
  11. #include <__availability>
  12. #include <__concepts/constructible.h>
  13. #include <__concepts/destructible.h>
  14. #include <__concepts/invocable.h>
  15. #include <__config>
  16. #include <__stop_token/intrusive_shared_ptr.h>
  17. #include <__stop_token/stop_state.h>
  18. #include <__stop_token/stop_token.h>
  19. #include <__type_traits/is_nothrow_constructible.h>
  20. #include <__utility/forward.h>
  21. #include <__utility/move.h>
  22. #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
  23. # pragma GCC system_header
  24. #endif
  25. _LIBCPP_PUSH_MACROS
  26. #include <__undef_macros>
  27. _LIBCPP_BEGIN_NAMESPACE_STD
  28. #if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)
  29. template <class _Callback>
  30. class _LIBCPP_AVAILABILITY_SYNC stop_callback : private __stop_callback_base {
  31. static_assert(invocable<_Callback>,
  32. "Mandates: stop_callback is instantiated with an argument for the template parameter Callback that "
  33. "satisfies invocable.");
  34. static_assert(destructible<_Callback>,
  35. "Mandates: stop_callback is instantiated with an argument for the template parameter Callback that "
  36. "satisfies destructible.");
  37. public:
  38. using callback_type = _Callback;
  39. template <class _Cb>
  40. requires constructible_from<_Callback, _Cb>
  41. _LIBCPP_HIDE_FROM_ABI explicit stop_callback(const stop_token& __st,
  42. _Cb&& __cb) noexcept(is_nothrow_constructible_v<_Callback, _Cb>)
  43. : stop_callback(__private_tag{}, __st.__state_, std::forward<_Cb>(__cb)) {}
  44. template <class _Cb>
  45. requires constructible_from<_Callback, _Cb>
  46. _LIBCPP_HIDE_FROM_ABI explicit stop_callback(stop_token&& __st,
  47. _Cb&& __cb) noexcept(is_nothrow_constructible_v<_Callback, _Cb>)
  48. : stop_callback(__private_tag{}, std::move(__st.__state_), std::forward<_Cb>(__cb)) {}
  49. _LIBCPP_HIDE_FROM_ABI ~stop_callback() {
  50. if (__state_) {
  51. __state_->__remove_callback(this);
  52. }
  53. }
  54. stop_callback(const stop_callback&) = delete;
  55. stop_callback(stop_callback&&) = delete;
  56. stop_callback& operator=(const stop_callback&) = delete;
  57. stop_callback& operator=(stop_callback&&) = delete;
  58. private:
  59. _LIBCPP_NO_UNIQUE_ADDRESS _Callback __callback_;
  60. __intrusive_shared_ptr<__stop_state> __state_;
  61. friend __stop_callback_base;
  62. struct __private_tag {};
  63. template <class _StatePtr, class _Cb>
  64. _LIBCPP_HIDE_FROM_ABI explicit stop_callback(__private_tag, _StatePtr&& __state, _Cb&& __cb) noexcept(
  65. is_nothrow_constructible_v<_Callback, _Cb>)
  66. : __stop_callback_base([](__stop_callback_base* __cb_base) noexcept {
  67. // stop callback is supposed to only be called once
  68. std::forward<_Callback>(static_cast<stop_callback*>(__cb_base)->__callback_)();
  69. }),
  70. __callback_(std::forward<_Cb>(__cb)),
  71. __state_() {
  72. if (__state && __state->__add_callback(this)) {
  73. // st.stop_requested() was false and this is successfully added to the linked list
  74. __state_ = std::forward<_StatePtr>(__state);
  75. }
  76. }
  77. };
  78. template <class _Callback>
  79. _LIBCPP_AVAILABILITY_SYNC stop_callback(stop_token, _Callback) -> stop_callback<_Callback>;
  80. #endif // _LIBCPP_STD_VER >= 20
  81. _LIBCPP_END_NAMESPACE_STD
  82. _LIBCPP_POP_MACROS
  83. #endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && !defined(_LIBCPP_HAS_NO_THREADS)