MySQL 9.6.0
Source Code Documentation
nonthrowing_boundary_container_adaptor.h
Go to the documentation of this file.
1// Copyright (c) 2024, 2025, Oracle and/or its affiliates.
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License, version 2.0,
5// as published by the Free Software Foundation.
6//
7// This program is designed to work with certain software (including
8// but not limited to OpenSSL) that is licensed under separate terms,
9// as designated in a particular file or component or in included license
10// documentation. The authors of MySQL hereby grant you an additional
11// permission to link the program and your derivative works with the
12// separately licensed software that they have either included with
13// the program or referenced in the documentation.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License, version 2.0, for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
24#ifndef MYSQL_SETS_NONTHROWING_BOUNDARY_CONTAINER_ADAPTOR_H
25#define MYSQL_SETS_NONTHROWING_BOUNDARY_CONTAINER_ADAPTOR_H
26
27/// @file
28/// Experimental API header
29
30#include "mysql/allocators/memory_resource.h" // Memory_resource
31#include "mysql/meta/is_same_ignore_const.h" // Is_same_ignore_const
32#include "mysql/sets/boundary_set_interface.h" // Basic_boundary_container_wrapper
33#include "mysql/sets/boundary_set_meta.h" // Is_boundary_container
34#include "mysql/utils/call_and_catch.h" // call_and_catch
35
36/// @addtogroup GroupLibsMysqlSets
37/// @{
38
39namespace mysql::sets {
40
41/// Non-throwing container that stores boundaries.
42///
43/// This implements the Is_boundary_set concept, and additionally has
44/// functionality for in-place union, intersection, and subtraction, as well as
45/// copy from another Boundary_set and making this container empty.
46///
47/// This is only wrappers around @c throwing::Boundary_container.
48template <Is_boundary_container Throwing_boundary_container_tp>
49 requires std::is_nothrow_default_constructible_v<
50 Throwing_boundary_container_tp> &&
51 std::is_nothrow_destructible_v<Throwing_boundary_container_tp>
54 Nonthrowing_boundary_container_adaptor<
55 Throwing_boundary_container_tp>,
56 Throwing_boundary_container_tp, mysql::utils::Shall_catch::yes> {
57 public:
58 using Throwing_boundary_container_t = Throwing_boundary_container_tp;
59 using Iterator_t =
63 using Set_traits_t = Throwing_boundary_container_t::Set_traits_t;
64 using Element_t = Set_traits_t::Element_t;
65 using Storage_t = Throwing_boundary_container_t::Storage_t;
67 using Allocator_t = typename Throwing_boundary_container_t::Allocator_t;
68 using This_t =
72 Throwing_boundary_container_tp, mysql::utils::Shall_catch::yes>;
73
74 static constexpr bool has_fast_insertion =
75 Throwing_boundary_container_t::has_fast_insertion;
76
77 /// Default constructor.
79
80 // Default move semantics and destructor if it is non-throwing. Delete
81 // copy-semantics since it is inherently throwing.
84 This_t &operator=(const This_t &other) = delete;
85 This_t &operator=(This_t &&other) noexcept = default;
87
88 /// Construct using the given Memory_resource.
90 const Memory_resource_t &memory_resource) noexcept
91 : Base_t(memory_resource) {}
92
93 /// Return a non-const reference to the underlying, throwing boundary
94 /// container.
95 [[nodiscard]] auto &throwing() noexcept { return this->wrapped(); }
96
97 /// Return a const reference to the underlying, throwing boundary container.
98 [[nodiscard]] const auto &throwing() const noexcept {
99 return this->wrapped();
100 }
101
102 /// Return a non-const reference to the underlying storage.
103 [[nodiscard]] auto &storage() noexcept { return this->wrapped().storage(); }
104
105 /// Return a const reference to the underlying storage.
106 [[nodiscard]] const auto &storage() const noexcept {
107 return this->wrapped().storage();
108 }
109
110 /// Insert the given element (inplace union).
111 ///
112 /// This may insert a new one-element interval, extend an existing interval at
113 /// one end, merge two intervals that were separated by only the given
114 /// element, or, if the element was already in this container, do nothing.
115 ///
116 /// @param element The element to insert.
117 ///
118 /// @retval Return_status::ok Success
119 ///
120 /// @retval Return_status::error An out-of-memory condition occurred while
121 /// inserting the interval. This leaves the container unmodified.
122 [[nodiscard]] auto insert(const Element_t &element) noexcept {
123 return mysql::utils::call_and_catch([&] { throwing().insert(element); });
124 }
125
126 /// Remove the given element (inplace subtraction).
127 ///
128 /// This may split an interval into two parts, shorten an existing interval in
129 /// one end, remove a one-element interval, or, if the element was not in this
130 /// container, do nothing.
131 ///
132 /// @param element The element to remove.
133 ///
134 /// @retval Return_status::ok Success
135 ///
136 /// @retval Return_status::error An out-of-memory condition occurred while
137 /// splitting an interval. This leaves the container unmodified.
138 [[nodiscard]] auto remove(const Element_t &element) noexcept {
139 return mysql::utils::call_and_catch([&] { throwing().remove(element); });
140 }
141
142 /// Insert the given interval (inplace union).
143 ///
144 /// This may merge intervals that overlap or are adjacent to the given
145 /// interval, or insert the interval between existing intervals, or, if the
146 /// interval was a subset of this container, do nothing.
147 ///
148 /// @param start The left boundary of the interval, inclusive.
149 ///
150 /// @param exclusive_end The right boundary of the interval, exclusive.
151 ///
152 /// @retval Return_status::ok Success
153 ///
154 /// @retval Return_status::error An out-of-memory condition occurred while
155 /// inserting the interval. This leaves the container unmodified.
156 [[nodiscard]] auto inplace_union(const Element_t &start,
157 const Element_t &exclusive_end) noexcept {
158 return mysql::utils::call_and_catch(
159 [&] { throwing().inplace_union(start, exclusive_end); });
160 }
161
162 /// Insert the given interval (inplace union), reading and updating the given
163 /// cursor.
164 ///
165 /// This may merge intervals that overlap or are adjacent to the given
166 /// interval, or insert the interval between existing intervals, or, if the
167 /// interval was a subset of this container, do nothing.
168 ///
169 /// @param[in,out] cursor Hint for the insertion position. If it refers to
170 /// `lower_bound(start)`, this function finds the insertion position in O(1);
171 /// if it refers to a boundary less than `lower_bound(start)`, it may reduce
172 /// the search space when finding the insertion position; otherwise, the hint
173 /// is ignored and the entire set has to be searched. It will be updated to
174 /// `upper_bound(exclusive_end)`, which makes it perfect to reuse for future
175 /// calls to this function, with intervals following this one.
176 ///
177 /// @param start The left boundary of the interval, inclusive.
178 ///
179 /// @param exclusive_end The right boundary of the interval, exclusive.
180 ///
181 /// @retval Return_status::ok Success
182 ///
183 /// @retval Return_status::error An out-of-memory condition occurred while
184 /// inserting the interval. This leaves the container unmodified.
185 [[nodiscard]] auto inplace_union(Iterator_t &cursor, const Element_t &start,
186 const Element_t &exclusive_end) noexcept {
187 return mysql::utils::call_and_catch(
188 [&] { throwing().inplace_union(cursor, start, exclusive_end); });
189 }
190
191 /// In-place insert the intervals of the given set into this container
192 /// (inplace union).
193 ///
194 /// This may merge intervals that overlap or are adjacent to a given interval,
195 /// and/or insert intervals between existing intervals, or, if the set
196 /// was a subset of this container, do nothing.
197 ///
198 /// This uses one of two algorithms, depending on the nature of the underlying
199 /// container:
200 ///
201 /// - If the underlying container supports fast insertion in the middle (e.g.
202 /// set or list), then it uses a true in-place algorithm, possibly adjusting
203 /// endpoints of existing intervals, and reusing memory as much as possible.
204 ///
205 /// - Otherwise (e.g. sorted vector), it uses an out-of-place algorithm that
206 /// computes the result in a new container and then move-assigns the new
207 /// container to the current container.
208 ///
209 /// The complexity depends on the underlying container:
210 ///
211 /// - set: O(number_of_removed_intervals + input.size() * log(this->size()))
212 ///
213 /// - list: Normally, O(input.size() + this->size()); or O(input.size()) if
214 /// input_set.front() >= this->back().
215 ///
216 /// - vector: Normally, O(input.size() + this->size()); or O(input.size()) if
217 /// input_set.front() >= this->back().
218 ///
219 /// @param input_set The input set.
220 ///
221 /// @retval Return_status::ok Success
222 ///
223 /// @retval Return_status::error An out-of-memory condition occurred while
224 /// inserting an interval. This may occur when the operation is
225 /// half-completed, which may leave the container as a superset of the
226 /// previous set and a subset of the union.
227 template <Is_boundary_set_over_traits_unqualified<Set_traits_t> Input_set_t>
228 [[nodiscard]] auto inplace_union(Input_set_t &&input_set) noexcept {
229 return mysql::utils::call_and_catch([&]() DEDUCED_NOEXCEPT_FUNCTION(
230 throwing().inplace_union(std::forward<Input_set_t>(input_set))));
231 }
232
233 /// Subtract the given interval.
234 ///
235 /// This may split an interval into two parts, shorten an existing interval in
236 /// one end, remove a one-element interval, or, if the element was not in this
237 /// container, do nothing.
238 ///
239 /// This may truncate and/or split intervals that overlap partially with the
240 /// subtracted interval, and remove intervals that overlap completely with the
241 /// subtracted interval.
242 ///
243 /// @param start The left boundary of the interval, inclusive.
244 ///
245 /// @param exclusive_end The right boundary of the interval, exclusive.
246 ///
247 /// @retval Return_status::ok Success
248 ///
249 /// @retval Return_status::error An out-of-memory condition occurred while
250 /// splitting an interval. This leaves the container unmodified.
251 [[nodiscard]] auto inplace_subtract(const Element_t &start,
252 const Element_t &exclusive_end) noexcept {
253 return mysql::utils::call_and_catch(
254 [&] { throwing().inplace_subtract(start, exclusive_end); });
255 }
256
257 /// Subtract the given interval, reading and updating the given cursor.
258 ///
259 /// This may truncate and/or split intervals that overlap partially with the
260 /// subtracted interval, and remove intervals that overlap completely with the
261 /// subtracted interval.
262 ///
263 /// @param[in,out] cursor Hint for the insertion position. If it refers to
264 /// `lower_bound(start)`, this function finds the insertion position in O(1);
265 /// if it refers to a boundary less than `lower_bound(start)`, it may reduce
266 /// the search space when finding the insertion position; otherwise, the hint
267 /// is ignored and the entire set has to be searched. It will be updated to
268 /// `upper_bound(exclusive_end)`, which makes it perfect to reuse for future
269 /// calls to this function, with intervals following this one.
270 ///
271 /// @param start The left boundary of the interval, inclusive.
272 ///
273 /// @param exclusive_end The right boundary of the interval, exclusive.
274 ///
275 /// @retval Return_status::ok Success
276 ///
277 /// @retval Return_status::error An out-of-memory condition occurred while
278 /// splitting an interval. This leaves the container unmodified.
279 [[nodiscard]] auto inplace_subtract(Iterator_t &cursor,
280 const Element_t &start,
281 const Element_t &exclusive_end) noexcept {
282 return mysql::utils::call_and_catch(
283 [&] { throwing().inplace_subtract(cursor, start, exclusive_end); });
284 }
285
286 /// In-place subtract intervals of the given container from this container.
287 ///
288 /// This may truncate and/or split intervals that overlap partially with
289 /// subtracted intervals, and remove intervals that overlap completely with
290 /// subtracted intervals.
291 ///
292 /// Algorithm and complexity: @see inplace_union.
293 ///
294 /// @param input_set The input set.
295 ///
296 /// @retval Return_status::ok Success
297 ///
298 /// @retval Return_status::error An out-of-memory condition occurred while
299 /// splitting an interval. This may occur when the operation is
300 /// half-completed, which may leave the container as a subset of the previous
301 /// set and a superset of the difference.
302 template <Is_boundary_set_over_traits_unqualified<Set_traits_t> Input_set_t>
303 [[nodiscard]] auto inplace_subtract(Input_set_t &&input_set) noexcept {
304 return mysql::utils::call_and_catch([&]() DEDUCED_NOEXCEPT_FUNCTION(
305 throwing().inplace_subtract(std::forward<Input_set_t>(input_set))));
306 }
307
308 /// In-place intersect this container with the given interval.
309 ///
310 /// This may truncate intervals that overlap partially with the given
311 /// interval, and remove intervals that are disjoint from the given interval.
312 ///
313 /// @param start The left boundary of the interval, inclusive.
314 ///
315 /// @param exclusive_end The right boundary of the interval, exclusive.
316 ///
317 /// If the underlying boundary container cannot throw, this returns void.
318 /// Otherwise, retursn Return_status::ok on success and Return_status::error
319 /// on out-of-memory error.
320 [[nodiscard]] auto inplace_intersect(
321 const Element_t &start, const Element_t &exclusive_end) noexcept {
322 return mysql::utils::call_and_catch([&]() DEDUCED_NOEXCEPT_FUNCTION(
323 this->throwing().inplace_intersect(start, exclusive_end)));
324 }
325
326 /// In-place intersect this container with intervals of the given container.
327 ///
328 /// This may truncate intervals that overlap partially with one interval from
329 /// the given set, split intervals that overlap partially with more
330 /// than one interval from the given set, and remove intervals that are
331 /// disjoint from the given interval set.
332 ///
333 /// Algorithm and complexity: @see inplace_union.
334 ///
335 /// @param input_set The input set.
336 ///
337 /// @retval Return_status::ok Success
338 ///
339 /// @retval Return_status::error An out-of-memory condition occurred while
340 /// splitting an interval. This may occur when the operation is
341 /// half-completed, which may leave the container as a subset of the previous
342 /// set and a superset of the intersection.
343 template <Is_boundary_set_over_traits_unqualified<Set_traits_t> Input_set_t>
344 [[nodiscard]] auto inplace_intersect(Input_set_t &&input_set) noexcept {
345 return mysql::utils::call_and_catch([&]() DEDUCED_NOEXCEPT_FUNCTION(
347 std::forward<Input_set_t>(input_set))));
348 }
349
350 /// Return iterator to the leftmost boundary at or after `cursor` that is
351 /// greater than the given element.
352 [[nodiscard]] static auto upper_bound_impl(
353 mysql::meta::Is_same_ignore_const<This_t> auto &self, const auto &cursor,
354 const Element_t &element) noexcept {
355 return Throwing_boundary_container_t::upper_bound_impl(self.throwing(),
356 cursor, element);
357 }
358
359 /// Return iterator to the leftmost boundary at or after `cursor` that is
360 /// greater than or equal to the given element.
361 [[nodiscard]] static auto lower_bound_impl(
362 mysql::meta::Is_same_ignore_const<This_t> auto &self, const auto &cursor,
363 const Element_t &element) noexcept {
364 return Throwing_boundary_container_t::lower_bound_impl(self.throwing(),
365 cursor, element);
366 }
367}; // class Nonthrowing_boundary_container_adaptor
368
369} // namespace mysql::sets
370
371// addtogroup GroupLibsMysqlSets
372/// @}
373
374#endif // ifndef MYSQL_SETS_NONTHROWING_BOUNDARY_CONTAINER_ADAPTOR_H
Experimental API header.
Experimental API header.
Experimental API header.
#define DEDUCED_NOEXCEPT_FUNCTION(X)
Helper macro to define a function that returns the result of a single expression, and has a condition...
Definition: call_and_catch.h:151
Polymorphism-free memory resource class with custom allocator and deallocator functions.
Definition: memory_resource.h:88
CRTP base class (mixin) to define a wrapper around a container.
Definition: basic_container_wrapper.h:59
CRTP base class/mixin, used to implement Boundary Sets that are container wrappers.
Definition: boundary_set_interface.h:128
Definition: basic_set_container_wrapper.h:47
Non-throwing container that stores boundaries.
Definition: nonthrowing_boundary_container_adaptor.h:56
const auto & storage() const noexcept
Return a const reference to the underlying storage.
Definition: nonthrowing_boundary_container_adaptor.h:106
auto inplace_union(Iterator_t &cursor, const Element_t &start, const Element_t &exclusive_end) noexcept
Insert the given interval (inplace union), reading and updating the given cursor.
Definition: nonthrowing_boundary_container_adaptor.h:185
Throwing_boundary_container_tp Throwing_boundary_container_t
Definition: nonthrowing_boundary_container_adaptor.h:58
auto inplace_intersect(const Element_t &start, const Element_t &exclusive_end) noexcept
In-place intersect this container with the given interval.
Definition: nonthrowing_boundary_container_adaptor.h:320
static constexpr bool has_fast_insertion
Definition: nonthrowing_boundary_container_adaptor.h:74
auto remove(const Element_t &element) noexcept
Remove the given element (inplace subtraction).
Definition: nonthrowing_boundary_container_adaptor.h:138
Nonthrowing_boundary_container_adaptor() noexcept=default
Default constructor.
auto & throwing() noexcept
Return a non-const reference to the underlying, throwing boundary container.
Definition: nonthrowing_boundary_container_adaptor.h:95
typename Throwing_boundary_container_t::Allocator_t Allocator_t
Definition: nonthrowing_boundary_container_adaptor.h:67
auto & storage() noexcept
Return a non-const reference to the underlying storage.
Definition: nonthrowing_boundary_container_adaptor.h:103
const auto & throwing() const noexcept
Return a const reference to the underlying, throwing boundary container.
Definition: nonthrowing_boundary_container_adaptor.h:98
auto inplace_intersect(Input_set_t &&input_set) noexcept
In-place intersect this container with intervals of the given container.
Definition: nonthrowing_boundary_container_adaptor.h:344
auto inplace_subtract(Iterator_t &cursor, const Element_t &start, const Element_t &exclusive_end) noexcept
Subtract the given interval, reading and updating the given cursor.
Definition: nonthrowing_boundary_container_adaptor.h:279
static auto lower_bound_impl(mysql::meta::Is_same_ignore_const< This_t > auto &self, const auto &cursor, const Element_t &element) noexcept
Return iterator to the leftmost boundary at or after cursor that is greater than or equal to the give...
Definition: nonthrowing_boundary_container_adaptor.h:361
static auto upper_bound_impl(mysql::meta::Is_same_ignore_const< This_t > auto &self, const auto &cursor, const Element_t &element) noexcept
Return iterator to the leftmost boundary at or after cursor that is greater than the given element.
Definition: nonthrowing_boundary_container_adaptor.h:352
auto inplace_union(Input_set_t &&input_set) noexcept
In-place insert the intervals of the given set into this container (inplace union).
Definition: nonthrowing_boundary_container_adaptor.h:228
auto insert(const Element_t &element) noexcept
Insert the given element (inplace union).
Definition: nonthrowing_boundary_container_adaptor.h:122
Throwing_boundary_container_t::Storage_t Storage_t
Definition: nonthrowing_boundary_container_adaptor.h:65
auto inplace_subtract(Input_set_t &&input_set) noexcept
In-place subtract intervals of the given container from this container.
Definition: nonthrowing_boundary_container_adaptor.h:303
auto inplace_subtract(const Element_t &start, const Element_t &exclusive_end) noexcept
Subtract the given interval.
Definition: nonthrowing_boundary_container_adaptor.h:251
auto inplace_union(const Element_t &start, const Element_t &exclusive_end) noexcept
Insert the given interval (inplace union).
Definition: nonthrowing_boundary_container_adaptor.h:156
Iterator_tp Iterator_t
Definition: boundary_set_interface.h:75
Set_traits_tp Set_traits_t
Definition: boundary_set_interface.h:78
typename Set_traits_tp::Element_t Element_t
Definition: boundary_set_interface.h:79
Const_iterator_tp Const_iterator_t
Definition: boundary_set_interface.h:76
true if Type1 and Type2 are equal, const-ness ignored
Definition: is_same_ignore_const.h:39
static void start(mysql_harness::PluginFuncEnv *env)
Definition: http_auth_backend_plugin.cc:180
Experimental API header.
Class that wraps resources in a polymorphic manner.
std::remove_cvref_t< decltype(std::declval< const Range_t >().begin())> Range_const_iterator_type
Gives the const_iterator type, deduced from the begin() const member.
Definition: meta.h:47
std::remove_cvref_t< decltype(std::declval< Range_t >().begin())> Range_iterator_type
Gives the iterator type, deduced from the begin() member.
Definition: meta.h:42
Definition: gtid_set.h:183
noexcept
The return type for any call_and_catch(f, args...) call where f(args...) returns Type.
Definition: call_and_catch.h:76