Seastar
High performance C++ framework for concurrent servers
abort_source.hh
1 /*
2  * This file is open source software, licensed to you under the terms
3  * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4  * distributed with this work for additional information regarding copyright
5  * ownership. You may not use this file except in compliance with the License.
6  *
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an
13  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14  * KIND, either express or implied. See the License for the
15  * specific language governing permissions and limitations
16  * under the License.
17  */
18 /*
19  * Copyright (C) 2017 ScyllaDB.
20  */
21 
22 #pragma once
23 
24 #include <seastar/util/noncopyable_function.hh>
25 #include <seastar/util/optimized_optional.hh>
26 #include <seastar/util/std-compat.hh>
27 
28 #include <boost/intrusive/list.hpp>
29 
30 #include <exception>
31 
32 namespace bi = boost::intrusive;
33 
34 namespace seastar {
35 
38 
41 class abort_requested_exception : public std::exception {
42 public:
43  virtual const char* what() const noexcept override {
44  return "abort requested";
45  }
46 };
47 
51 class abort_source {
52  using subscription_callback_type = noncopyable_function<void() noexcept>;
53 
54 public:
58  class subscription : public bi::list_base_hook<bi::link_mode<bi::auto_unlink>> {
59  friend class abort_source;
60 
62 
64  : _target(std::move(target)) {
65  as._subscriptions->push_back(*this);
66  }
67 
68  void on_abort() {
69  _target();
70  }
71 
72  public:
73  subscription() = default;
74 
75  subscription(subscription&& other) noexcept(std::is_nothrow_move_constructible<subscription_callback_type>::value)
76  : _target(std::move(other._target)) {
77  subscription_list_type::node_algorithms::swap_nodes(other.this_ptr(), this_ptr());
78  }
79 
80  subscription& operator=(subscription&& other) noexcept(std::is_nothrow_move_assignable<subscription_callback_type>::value) {
81  if (this != &other) {
82  _target = std::move(other._target);
83  if (is_linked()) {
84  subscription_list_type::node_algorithms::unlink(this_ptr());
85  }
86  subscription_list_type::node_algorithms::swap_nodes(other.this_ptr(), this_ptr());
87  }
88  return *this;
89  }
90 
91  explicit operator bool() const noexcept {
92  return is_linked();
93  }
94  };
95 
96 private:
97  using subscription_list_type = bi::list<subscription, bi::constant_time_size<false>>;
98  std::optional<subscription_list_type> _subscriptions = subscription_list_type();
99 
100 public:
105  [[nodiscard]]
106  optimized_optional<subscription> subscribe(subscription_callback_type f) noexcept(std::is_nothrow_move_constructible<subscription_callback_type>::value) {
107  if (abort_requested()) {
108  return { };
109  }
110  return { subscription(*this, std::move(f)) };
111  }
112 
115  void request_abort() {
116  _subscriptions->clear_and_dispose([] (subscription* s) { s->on_abort(); });
117  _subscriptions = { };
118  }
119 
121  bool abort_requested() const noexcept {
122  return !_subscriptions;
123  }
124 
125 
127  void check() const {
128  if (abort_requested()) {
130  }
131  }
132 };
133 
135 
136 }
Definition: abort_source.hh:41
Definition: abort_source.hh:58
Definition: abort_source.hh:51
void check() const
Throws a abort_requested_exception if cancellation has been requested.
Definition: abort_source.hh:127
optimized_optional< subscription > subscribe(subscription_callback_type f) noexcept(std::is_nothrow_move_constructible< subscription_callback_type >::value)
Definition: abort_source.hh:106
void request_abort()
Definition: abort_source.hh:115
bool abort_requested() const noexcept
Returns whether an abort has been requested.
Definition: abort_source.hh:121
Definition: optimized_optional.hh:49
Seastar API namespace.
Definition: abort_on_ebadf.hh:24
Definition: noncopyable_function.hh:33