master
  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
 10#ifndef _LIBCPP___STOP_TOKEN_STOP_CALLBACK_H
 11#define _LIBCPP___STOP_TOKEN_STOP_CALLBACK_H
 12
 13#include <__concepts/constructible.h>
 14#include <__concepts/destructible.h>
 15#include <__concepts/invocable.h>
 16#include <__config>
 17#include <__stop_token/intrusive_shared_ptr.h>
 18#include <__stop_token/stop_state.h>
 19#include <__stop_token/stop_token.h>
 20#include <__type_traits/is_nothrow_constructible.h>
 21#include <__utility/forward.h>
 22#include <__utility/move.h>
 23#include <__utility/private_constructor_tag.h>
 24
 25#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 26#  pragma GCC system_header
 27#endif
 28
 29_LIBCPP_PUSH_MACROS
 30#include <__undef_macros>
 31
 32_LIBCPP_BEGIN_NAMESPACE_STD
 33
 34#if _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_THREADS
 35
 36template <class _Callback>
 37class _LIBCPP_AVAILABILITY_SYNC stop_callback : private __stop_callback_base {
 38  static_assert(invocable<_Callback>,
 39                "Mandates: stop_callback is instantiated with an argument for the template parameter Callback that "
 40                "satisfies invocable.");
 41  static_assert(destructible<_Callback>,
 42                "Mandates: stop_callback is instantiated with an argument for the template parameter Callback that "
 43                "satisfies destructible.");
 44
 45public:
 46  using callback_type = _Callback;
 47
 48  template <class _Cb>
 49    requires constructible_from<_Callback, _Cb>
 50  _LIBCPP_HIDE_FROM_ABI explicit stop_callback(const stop_token& __st,
 51                                               _Cb&& __cb) noexcept(is_nothrow_constructible_v<_Callback, _Cb>)
 52      : stop_callback(__private_constructor_tag{}, __st.__state_, std::forward<_Cb>(__cb)) {}
 53
 54  template <class _Cb>
 55    requires constructible_from<_Callback, _Cb>
 56  _LIBCPP_HIDE_FROM_ABI explicit stop_callback(stop_token&& __st,
 57                                               _Cb&& __cb) noexcept(is_nothrow_constructible_v<_Callback, _Cb>)
 58      : stop_callback(__private_constructor_tag{}, std::move(__st.__state_), std::forward<_Cb>(__cb)) {}
 59
 60  _LIBCPP_HIDE_FROM_ABI ~stop_callback() {
 61    if (__state_) {
 62      __state_->__remove_callback(this);
 63    }
 64  }
 65
 66  stop_callback(const stop_callback&)            = delete;
 67  stop_callback(stop_callback&&)                 = delete;
 68  stop_callback& operator=(const stop_callback&) = delete;
 69  stop_callback& operator=(stop_callback&&)      = delete;
 70
 71private:
 72  _LIBCPP_NO_UNIQUE_ADDRESS _Callback __callback_;
 73  __intrusive_shared_ptr<__stop_state> __state_;
 74
 75  friend __stop_callback_base;
 76
 77  template <class _StatePtr, class _Cb>
 78  _LIBCPP_HIDE_FROM_ABI explicit stop_callback(__private_constructor_tag, _StatePtr&& __state, _Cb&& __cb) noexcept(
 79      is_nothrow_constructible_v<_Callback, _Cb>)
 80      : __stop_callback_base([](__stop_callback_base* __cb_base) noexcept {
 81          // stop callback is supposed to only be called once
 82          std::forward<_Callback>(static_cast<stop_callback*>(__cb_base)->__callback_)();
 83        }),
 84        __callback_(std::forward<_Cb>(__cb)),
 85        __state_() {
 86    if (__state && __state->__add_callback(this)) {
 87      // st.stop_requested() was false and this is successfully added to the linked list
 88      __state_ = std::forward<_StatePtr>(__state);
 89    }
 90  }
 91};
 92
 93template <class _Callback>
 94_LIBCPP_AVAILABILITY_SYNC stop_callback(stop_token, _Callback) -> stop_callback<_Callback>;
 95
 96#endif // _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_THREADS
 97
 98_LIBCPP_END_NAMESPACE_STD
 99
100_LIBCPP_POP_MACROS
101
102#endif // _LIBCPP___STOP_TOKEN_STOP_CALLBACK_H