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