MySQL 9.6.0
Source Code Documentation
interval_container.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_INTERVAL_CONTAINER_H
25#define MYSQL_SETS_INTERVAL_CONTAINER_H
26
27/// @file
28/// Experimental API header
29
30#include "mysql/allocators/memory_resource.h" // Memory_resource
31#include "mysql/sets/boundary_set_meta.h" // Is_boundary_set
32#include "mysql/sets/interval.h" // Interval
33#include "mysql/sets/interval_set_interface.h" // Interval_set_interface
34#include "mysql/sets/interval_set_meta.h" // Is_interval_set_over_traits
35#include "mysql/utils/is_same_object.h" // is_same_object
36
37/// @addtogroup GroupLibsMysqlSets
38/// @{
39
40namespace mysql::sets {
41
42/// Container for intervals.
43///
44/// @tparam Boundary_container_tp Boundary container, i.e., a Boundary
45/// set capable of storing the data, and computing inplace operations.
46template <Is_boundary_container Boundary_container_tp>
48 : public Interval_set_interface<Interval_container<Boundary_container_tp>,
49 Boundary_container_tp> {
50 public:
51 using Boundary_container_t = Boundary_container_tp;
53
54 private:
56
57 public:
59 using Allocator_t = typename Boundary_container_t::Allocator_t;
60 using typename Base_t::Const_iterator_t;
61 using typename Base_t::Element_t;
62 using typename Base_t::Iterator_t;
63 using typename Base_t::Set_traits_t;
64 using Boundary_iterator_t = typename Boundary_container_t::Iterator_t;
67
68 private:
69 // True if 'insert' does not throw. We assume that this implies that all
70 // modifications are non-throwing.
71 static constexpr bool noexcept_insertions = noexcept(
72 std::declval<Boundary_container_t>().insert(std::declval<Element_t>()));
73
74 public:
75 static constexpr bool has_fast_insertion =
76 Boundary_container_t::has_fast_insertion;
77
78 /// Default constructor.
80
81 /// Copy constructor.
82 ///
83 /// This copy constructor is only enabled when the underlying boundary
84 /// container is throwing. For non-throwing containers, use the default
85 /// constructor followed by the assign member function instead.
86 ///
87 /// @throws bad_alloc This may occur when the operation is half-completed,
88 /// which may leave the container as a subset of @c source.
90
91 /// Move constructor, defaulted.
93
94 /// Copy assignment operator.
95 ///
96 /// This copy assignment operator is only enabled when the underlying boundary
97 /// container is throwing. For non-throwing containers, use assign instead.
98 ///
99 /// @throws bad_alloc This may occur when the operation is half-completed,
100 /// which may leave the container as a subset of @c source.
101 Interval_container &operator=(const Interval_container &source) = default;
102
103 /// Move assignment operator, defaulted.
105
106 /// Destructor.
107 ///
108 /// This is defaulted, so it will just invoke the destructor for m_boundaries.
110
111 /// Construct an empty container using the specified Memory_resource.
112 explicit Interval_container(const Memory_resource_t &memory_resource) noexcept
113 : m_boundaries(memory_resource) {}
114
115 /// Construct by copying any other Interval_set over the same boundary traits.
116 ///
117 /// This copy constructor is only enabled when the underlying boundary
118 /// container is copy-constructible, i.e., when it is throwing. For
119 /// non-throwing containers, use the default constructor followed by the
120 /// assign member function instead.
121 ///
122 /// @throws bad_alloc This may occur when the operation is half-completed,
123 /// which may leave the container as a subset of @c source.
126 : m_boundaries(
129
130 /// Construct by copying any other Interval_set over the same boundary traits.
131 ///
132 /// This copy constructor is only enabled when the underlying boundary
133 /// container is copy-constructible, i.e., when it is throwing. For
134 /// non-throwing containers, use the default constructor followed by the
135 /// assign member function instead.
136 ///
137 /// @throws bad_alloc This may occur when the operation is half-completed,
138 /// which may leave the container as a subset of @c source.
141 const Memory_resource_t &memory_resource)
142 : m_boundaries(source.boundaries(), memory_resource) {}
143
144 /// Assign from any other Boundary_set over the same Set traits.
145 ///
146 /// This copy assignment operator is only enabled when the underlying boundary
147 /// container is copy-constructible, i.e., when it is throwing. For
148 /// non-throwing containers, use assign instead.
149 ///
150 /// @throws bad_alloc This may occur when the operation is half-completed,
151 /// which may leave the container as a subset of @c source.
154 boundaries() = source.boundaries();
155 return *this;
156 }
157
158 /// Overwrite this object with @c source (copy-assigned).
159 ///
160 /// This is equivalent to the copy assignment operator, and provided only in
161 /// order for uniformity of this API and the non-throwing API.
162 ///
163 /// If the boundary underlying set cannot fail (e.g. the argument is an rvalue
164 /// reference to a type satisfying Can_donate_set), this returns void and
165 /// does not throw. Otherwise, out-of-memory conditions may be possible. Then,
166 /// if an out-of-memory condition occurred while inserting the interval, this
167 /// returns error or throws bad_alloc according to the underlying boundary
168 /// container. If the out-of-memory condition occurs when the operation is
169 /// half-completed, it may leave the container as a subset of @c source.
170 template <Is_interval_set_over_traits_unqualified<Set_traits_t> Source_t>
171 [[nodiscard]] auto assign(Source_t &&source)
172#ifdef IN_DOXYGEN
173 ; // doxygen can't parse the macro below
174#else
176 std::forward<Source_t>(source).boundaries()))
177#endif
178
179 /// Return the Memory_resource object that manages memory in this object,
180 /// or a default-constructed Memory_resource if there is none.
181 [[nodiscard]] decltype(auto) get_memory_resource() const noexcept {
183 }
184
185 /// Make this container empty.
186 ///
187 /// This function cannot fail.
188 void clear() noexcept { boundaries().clear(); }
189
190 /// Return an lvalue reference to the underlying boundary container. The
191 /// caller may modify the container through that reference, which will affect
192 /// this interval container.
193 [[nodiscard]] auto &boundaries() &noexcept { return m_boundaries; }
194
195 /// Return a const lvalue reference to the underlying boundary container.
196 [[nodiscard]] const auto &boundaries() const &noexcept {
197 return m_boundaries;
198 }
199
200 /// Return an rvalue reference to the underlying boundary container. The
201 /// caller may modify the container through that reference, which will affect
202 /// this interval container.
203 [[nodiscard]] auto &&boundaries() &&noexcept {
204 return std::move(m_boundaries);
205 }
206
207 /// Insert the given element (inplace union).
208 ///
209 /// This may merge adjacent intervals.
210 ///
211 /// @param element The element to insert.
212 ///
213 /// If an out-of-memory condition occurred while inserting the interval, this
214 /// returns error or throws bad_alloc according to the underlying boundary
215 /// container. This leaves the container unmodified.
216 ///
217 /// We use [[nodiscard]] rather than [[nodiscard]], because nodiscard gives
218 /// a warning even if auto resolves to void, whereas nodiscard does not.
219 [[nodiscard]] auto insert(const Element_t &element)
220#ifdef IN_DOXYGEN
221 ; // doxygen can't parse the macro below
222#else
224#endif
225
226 /// Remove the given element (inplace subtraction).
227 ///
228 /// This may truncate and/or split an interval that overlaps with the
229 /// subtracted interval.
230 ///
231 /// @param element The element to remove.
232 ///
233 /// If an out-of-memory condition occurred while splitting an interval, this
234 /// returns error or throws bad_alloc according to the underlying boundary
235 /// container. This leaves the container unmodified.
236 [[nodiscard]] auto remove(const Element_t &element)
237#ifdef IN_DOXYGEN
238 ; // doxygen can't parse the macro below
239#else
241#endif
242
243 /// Insert the given interval (inplace union).
244 ///
245 /// This may merge intervals that are overlapping or adjacent with the given
246 /// interval.
247 ///
248 /// @param interval The interval to insert.
249 ///
250 /// If an out-of-memory condition occurred while inserting an interval, this
251 /// returns error or throws bad_alloc according to the underlying boundary
252 /// container. This leaves the container unmodified.
253 [[nodiscard]] auto inplace_union(const Interval_t &interval)
254#ifdef IN_DOXYGEN
255 ; // doxygen can't parse the macro below
256#else
258 interval.start(), interval.exclusive_end()))
259#endif
260
261 /// Insert the given interval (inplace union), reading and updating the given
262 /// cursor.
263 ///
264 /// This may merge intervals that are overlapping or adjacent with the given
265 /// interval.
266 ///
267 /// @param[in,out] cursor Hint for the position. @see
268 /// Boundary_container::inplace_union.
269 ///
270 /// @param interval The interval to insert.
271 ///
272 /// If an out-of-memory condition occurred while inserting an interval, this
273 /// returns error or throws bad_alloc according to the underlying boundary
274 /// container. This leaves the container unmodified.
275 [[nodiscard]] auto inplace_union(Boundary_iterator_t &cursor,
276 const Interval_t &interval)
277#ifdef IN_DOXYGEN
278 ; // doxygen can't parse the macro below
279#else
281 cursor, interval.start(), interval.exclusive_end()))
282#endif
283
284 /// In-place insert the intervals of the given set into this container
285 /// (inplace union).
286 ///
287 /// This may merge intervals that are overlapping or adjacent.
288 ///
289 /// This uses one of two algorithms, depending on the nature of the underlying
290 /// storage:
291 ///
292 /// - If the underlying storage supports fast insertion in the middle (e.g.
293 /// set or list), then it uses a true in-place algorithm, possibly adjusting
294 /// existing intervals, and reusing memory as much as possible.
295 ///
296 /// - Otherwise (e.g. sorted vector), it uses an out-of-place algorithm that
297 /// computes the result in a new container and then move-assigns the new
298 /// container to the current container.
299 ///
300 /// The complexity depends on the underlying storage:
301 ///
302 /// - set: O(number_of_removed_intervals +
303 /// interval_set.size() * log(this->size()))
304 ///
305 /// - list: Normally O(interval_set.size() + this->size());
306 /// but O(interval_set.size()) if interval_set.front() >= this->back().
307 ///
308 /// - vector: Normally, O(interval_set.size() + this->size()); but
309 /// O(interval_set.size()) if interval_set.front() >= this->back().
310 ///
311 /// @param interval_set The interval set.
312 ///
313 /// If an out-of-memory condition occurred while inserting an interval, this
314 /// returns error or throws bad_alloc according to the underlying boundary
315 /// container. This may occur when the operation is half-completed, which
316 /// may leave the container as a superset of the previous set and a subset of
317 /// the union.
318 template <
320 [[nodiscard]] auto inplace_union(Interval_set_t &&interval_set)
321#ifdef IN_DOXYGEN
322 ; // doxygen can't parse the macro below
323#else
325 std::forward<Interval_set_t>(interval_set).boundaries()))
326#endif
327
328 /// Subtract the given interval.
329 ///
330 /// This may truncate and/or split intervals that overlap partially with the
331 /// subtracted interval, and remove intervals that overlap completely with the
332 /// subtracted interval.
333 ///
334 /// @param interval The interval to remove.
335 ///
336 /// If an out-of-memory condition occurred while splitting an interval, this
337 /// returns error or throws bad_alloc according to the underlying boundary
338 /// container. This leaves the container unmodified.
339 [[nodiscard]] auto inplace_subtract(const Interval_t &interval)
340#ifdef IN_DOXYGEN
341 ; // doxygen can't parse the macro below
342#else
344 interval.start(), interval.exclusive_end()))
345#endif
346
347 /// Subtract the given interval, reading and updating the given cursor.
348 ///
349 /// This may truncate and/or split intervals that overlap partially with the
350 /// subtracted interval, and remove intervals that overlap completely with the
351 /// subtracted interval.
352 ///
353 /// @param[in,out] cursor Hint for the position. @see
354 /// Boundary_container::inplace_subtract.
355 ///
356 /// @param interval The interval to remove.
357 ///
358 /// If an out-of-memory condition occurred while splitting an interval, this
359 /// returns error or throws bad_alloc according to the underlying boundary
360 /// container. This leaves the container unmodified.
361 [[nodiscard]] auto inplace_subtract(Boundary_iterator_t &cursor,
362 const Interval_t &interval)
363#ifdef IN_DOXYGEN
364 ; // doxygen can't parse the macro below
365#else
367 interval.start(), interval.exclusive_end(), cursor))
368#endif
369
370 /// In-place subtract intervals of the given set from this container.
371 ///
372 /// This may truncate and/or split intervals that overlap partially with
373 /// subtracted intervals, and remove intervals that overlap completely with
374 /// subtracted intervals.
375 ///
376 /// Algorithm and complexity: @see inplace_union.
377 ///
378 /// @param interval_set The interval set.
379 ///
380 /// If an out-of-memory condition occurred while splitting an interval, this
381 /// returns error or throws bad_alloc according to the underlying boundary
382 /// container. This may occur when the operation is half-completed, which may
383 /// leave the container as a subset of the previous set and a superset of the
384 /// difference.
385 template <
387 [[nodiscard]] auto inplace_subtract(Interval_set_t &&interval_set)
388#ifdef IN_DOXYGEN
389 ; // doxygen can't parse the macro below
390#else
392 std::forward<Interval_set_t>(interval_set).boundaries()))
393#endif
394
395 /// In-place intersect this container with the given interval.
396 ///
397 /// This may truncate intervals that overlap partially with the given
398 /// interval, and remove intervals that are disjoint from the given interval.
399 ///
400 /// Algorithm and complexity: @see inplace_union.
401 ///
402 /// @param interval The interval to intersect with.
403 ///
404 /// Since this cannot increase the number of intervals, it never fails.
405 void inplace_intersect(const Interval_t &interval) noexcept {
406 boundaries().inplace_intersect(interval.start(), interval.exclusive_end());
407 }
408
409 /// In-place intersect this container with the given set.
410 ///
411 /// This may truncate intervals that overlap partially with one interval from
412 /// the given set, split intervals that overlap partially with more
413 /// than one interval from the given set, and remove intervals that are
414 /// disjoint from the given interval set.
415 ///
416 /// Algorithm and complexity: @see inplace_union.
417 ///
418 /// @param interval_set The interval set.
419 ///
420 /// If an out-of-memory condition occurred while splitting an interval, this
421 /// returns error or throws bad_alloc according to the underlying boundary
422 /// container. This may occur when the operation is half-completed, which may
423 /// leave the container as a subset of the previous set and a superset of the
424 /// intersection.
425 template <
427 [[nodiscard]] auto inplace_intersect(Interval_set_t &&interval_set)
428#ifdef IN_DOXYGEN
429 ; // doxygen can't parse the macro below
430#else
433 std::forward<Interval_set_t>(interval_set).boundaries()))
434#endif
435
436 private:
438
439}; // class Interval_container
440
441} // namespace mysql::sets
442
443// addtogroup GroupLibsMysqlSets
444/// @}
445
446#endif // ifndef MYSQL_SETS_INTERVAL_CONTAINER_H
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 to provide members of a collection based on an implementation that provides begin/end...
Definition: collection_interface.h:90
const auto & source() const
Definition: disjoint_pairs.h:274
Container for intervals.
Definition: interval_container.h:49
const auto & boundaries() const &noexcept
Return a const lvalue reference to the underlying boundary container.
Definition: interval_container.h:196
auto inplace_union(Interval_set_t &&interval_set)
In-place insert the intervals of the given set into this container (inplace union).
auto assign(Source_t &&source)
Overwrite this object with source (copy-assigned).
static constexpr bool noexcept_insertions
Definition: interval_container.h:71
Interval_container(const Is_interval_set_over_traits< Set_traits_t > auto &source)
Construct by copying any other Interval_set over the same boundary traits.
Definition: interval_container.h:124
decltype(auto) get_memory_resource() const noexcept
Return the Memory_resource object that manages memory in this object, or a default-constructed Memory...
Definition: interval_container.h:181
typename Boundary_container_t::Allocator_t Allocator_t
Definition: interval_container.h:59
auto insert(const Element_t &element)
Insert the given element (inplace union).
auto inplace_subtract(Interval_set_t &&interval_set)
In-place subtract intervals of the given set from this container.
Storage_or_void< Boundary_container_t > Storage_t
Definition: interval_container.h:66
auto inplace_subtract(const Interval_t &interval)
Subtract the given interval.
Boundary_container_t m_boundaries
Definition: interval_container.h:437
Interval_container(const Is_interval_set_over_traits< Set_traits_t > auto &source, const Memory_resource_t &memory_resource)
Construct by copying any other Interval_set over the same boundary traits.
Definition: interval_container.h:139
auto remove(const Element_t &element)
Remove the given element (inplace subtraction).
auto & boundaries() &noexcept
Return an lvalue reference to the underlying boundary container.
Definition: interval_container.h:193
void inplace_intersect(const Interval_t &interval) noexcept
In-place intersect this container with the given interval.
Definition: interval_container.h:405
auto inplace_subtract(Boundary_iterator_t &cursor, const Interval_t &interval)
Subtract the given interval, reading and updating the given cursor.
auto && boundaries() &&noexcept
Return an rvalue reference to the underlying boundary container.
Definition: interval_container.h:203
void clear() noexcept
Make this container empty.
Definition: interval_container.h:188
Interval_container() noexcept=default
Default constructor.
auto inplace_union(const Interval_t &interval)
Insert the given interval (inplace union).
static constexpr bool has_fast_insertion
Definition: interval_container.h:75
Boundary_container_tp Boundary_container_t
Definition: interval_container.h:51
auto inplace_intersect(Interval_set_t &&interval_set)
In-place intersect this container with the given set.
typename Boundary_container_t::Iterator_t Boundary_iterator_t
Definition: interval_container.h:64
Interval_container & operator=(const Is_interval_set_over_traits< Set_traits_t > auto &source)
Assign from any other Boundary_set over the same Set traits.
Definition: interval_container.h:152
auto inplace_union(Boundary_iterator_t &cursor, const Interval_t &interval)
Insert the given interval (inplace union), reading and updating the given cursor.
CRTP base class used to define an Interval set based on an implementation having the member function ...
Definition: interval_set_interface.h:87
Boundary_set_t::Set_traits_t Set_traits_t
Definition: interval_set_interface.h:95
mysql::ranges::Disjoint_pairs_iterator< Boundary_const_iterator_t, Make_interval_t > Const_iterator_t
Definition: interval_set_interface.h:107
mysql::ranges::Disjoint_pairs_iterator< Boundary_iterator_t, Make_interval_t > Iterator_t
Definition: interval_set_interface.h:104
typename Set_traits_t::Element_t Element_t
Definition: interval_set_interface.h:96
Holds the start boundary and endpoint boundary of an interval.
Definition: interval.h:178
Definition: interval_set_meta.h:90
Experimental API header.
Experimental API header.
Experimental API header.
Experimental API header.
Class that wraps resources in a polymorphic manner.
static int interval
Definition: mysqladmin.cc:72
decltype(auto) get_memory_resource_or_default(const auto &object)
Return object.get_memory_resource(), if that function exists.
Definition: memory_resource.h:145
Definition: gtid_set.h:183
detail::Storage_or_void_helper< Container_t >::Type Storage_or_void
Type alias for Container_t::Storage_t if that exists, or void otherwise.
Definition: boundary_set_meta.h:378
noexcept
The return type for any call_and_catch(f, args...) call where f(args...) returns Type.
Definition: call_and_catch.h:76
Definition: instrumented_condition_variable.h:32