Seastar
High performance C++ framework for concurrent servers
io_intent.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 2021 ScyllaDB
20 */
21
22#pragma once
23
24#include <seastar/util/modules.hh>
25#ifndef SEASTAR_MODULE
26#include <utility>
27#include <boost/intrusive/list.hpp>
28#include <boost/intrusive/slist.hpp>
29#endif
30
31namespace bi = boost::intrusive;
32
33namespace seastar {
34
35SEASTAR_MODULE_EXPORT
36class io_intent;
37
38namespace internal {
39
40/*
41 * The tracker of cancellable sub-queue of requests.
42 *
43 * This queue is stuffed with requests that sit in the
44 * same IO queue for dispatching (there can be other requests
45 * as well) and ties them together for cancellation.
46 * This IO queue is the fair_queue's priority_class's one.
47 * Beware, if requests from different IO queues happen
48 * in the same cancellable queue the whole thing blows up.
49 */
50class cancellable_queue {
51public:
52 class link {
53 friend class cancellable_queue;
54
55 union {
56 cancellable_queue* _ref;
57 bi::slist_member_hook<> _hook;
58 };
59
60 public:
61 link() noexcept : _ref(nullptr) {}
62 ~link() { assert(_ref == nullptr); }
63
64 void enqueue(cancellable_queue& cq) noexcept {
65 cq.push_back(*this);
66 }
67
68 void maybe_dequeue() noexcept {
69 if (_ref != nullptr) {
70 _ref->pop_front();
71 }
72 }
73 };
74
75private:
76 static_assert(sizeof(link) == sizeof(void*), "cancellable_queue::link size is too big");
77 using list_of_links_t = bi::slist<link,
78 bi::constant_time_size<false>,
79 bi::cache_last<true>,
80 bi::member_hook<link, bi::slist_member_hook<>, &link::_hook>>;
81
82 link* _first;
83 list_of_links_t _rest;
84
85 void push_back(link& il) noexcept;
86 void pop_front() noexcept;
87
88public:
89 cancellable_queue() noexcept : _first(nullptr) {}
90 cancellable_queue(const cancellable_queue&) = delete;
91 cancellable_queue(cancellable_queue&& o) noexcept;
92 cancellable_queue& operator=(cancellable_queue&& o) noexcept;
93 ~cancellable_queue();
94};
95
96/*
97 * A "safe" reference on a intent. Safe here means that the original
98 * intent can be destroyed at any time and this reference will be
99 * updated not to point at it any longer.
100 * The retrieve() method brings the original intent back or throws
101 * and exception if the intent was cancelled.
102 */
103class intent_reference : public bi::list_base_hook<bi::link_mode<bi::auto_unlink>> {
104 friend class seastar::io_intent;
105 using container_type = bi::list<intent_reference, bi::constant_time_size<false>>;
106 static constexpr uintptr_t _cancelled_intent = 1;
107 io_intent* _intent;
108
109 void on_cancel() noexcept { _intent = reinterpret_cast<io_intent*>(_cancelled_intent); }
110 bool is_cancelled() const noexcept { return _intent == reinterpret_cast<io_intent*>(_cancelled_intent); }
111
112public:
113 intent_reference(io_intent* intent) noexcept;
114
115 intent_reference(intent_reference&& o) noexcept : _intent(std::exchange(o._intent, nullptr)) {
116 container_type::node_algorithms::swap_nodes(o.this_ptr(), this_ptr());
117 }
118
119 intent_reference& operator=(intent_reference&& o) noexcept {
120 if (this != &o) {
121 _intent = std::exchange(o._intent, nullptr);
122 unlink();
123 container_type::node_algorithms::swap_nodes(o.this_ptr(), this_ptr());
124 }
125 return *this;
126 }
127
128 io_intent* retrieve() const;
129};
130
131} // namespace internal
132
133} // namespace seastar
Definition: io_intent.hh:44
Seastar API namespace.
Definition: abort_on_ebadf.hh:26