MySQL 26.7.0
Source Code Documentation
ut0new.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 2014, 2026, Oracle and/or its affiliates.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License, version 2.0, as published by the
7Free Software Foundation.
8
9This program is designed to work with certain software (including
10but not limited to OpenSSL) that is licensed under separate terms,
11as designated in a particular file or component or in included license
12documentation. The authors of MySQL hereby grant you an additional
13permission to link the program and your derivative works with the
14separately licensed software that they have either included with
15the program or referenced in the documentation.
16
17This program is distributed in the hope that it will be useful, but WITHOUT
18ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
20for more details.
21
22You should have received a copy of the GNU General Public License along with
23this program; if not, write to the Free Software Foundation, Inc.,
2451 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
26*****************************************************************************/
27
28/** @file include/ut0new.h
29 Dynamic memory allocation routines and custom allocators specifically
30 crafted to support memory instrumentation through performance schema memory
31 engine (PFS).
32 */
33
34/** This file contains a set of libraries providing overloads for regular
35 dynamic allocation routines which allow for opt-in memory instrumentation
36 through performance schema memory engine (PFS).
37
38 In particular, _no_ regular dynamic allocation routines shall be used given
39 that the end goal of instrumentation through PFS is system observability
40 and resource control. In practice this means that we are off the chances to
41 use _any_ standard means of allocating the memory and that we have to
42 provide and re-implement our own PFS-aware variants ourselves.
43
44 This does not only apply to direct memory allocation through malloc or new
45 but also to data structures that may allocate dynamic memory under the hood,
46 like the ones from STL. For that reason, STL data structures shall always
47 be used with PFS-enabled custom memory allocator. STL algorithms OTOH
48 also _may_ allocate dynamic memory but they do not provide customization
49 point for user-code to provide custom memory allocation mechanism so there's
50 nothing that we can do about it.
51
52 Furthermore, facilities that allow safer memory management such as
53 std::unique_ptr, std::shared_ptr and their respective std::make_unique and
54 std::make_shared functions also have to be re-implemented as such so that
55 they become PFS-aware.
56
57 Following is the list of currently implemented PFS-enabled dynamic
58 allocation overloads and associated facilities:
59 * Primitive allocation functions:
60 * ut::malloc
61 * ut::zalloc
62 * ut::realloc
63 * ut::free
64 * ut::{malloc | zalloc | realloc}_withkey
65 * Primitive allocation functions for types with extended alignment:
66 * ut::aligned_alloc
67 * ut::aligned_zalloc
68 * ut::aligned_free
69 * ut::{aligned_alloc | aligned_zalloc}_withkey
70 * Primitive allocation functions for page-aligned allocations:
71 * ut::malloc_page
72 * ut::malloc_page_withkey
73 * ut::free_page
74 * Primitive allocation functions for large (huge) page aligned
75 allocations:
76 * ut::malloc_large_page
77 * ut::malloc_large_page_withkey
78 * ut::free_large_page
79 * Primitive allocation functions for large (huge) aligned allocations with
80 fallback to page-aligned allocations:
81 * ut::malloc_large_page(fallback_to_normal_page_t)
82 * ut::malloc_large_page_withkey(fallback_to_normal_page_t)
83 * ut::free_large_page(fallback_to_normal_page_t)
84 * Overloads for C++ new and delete syntax:
85 * ut::new_
86 * ut::new_arr
87 * ut::{new_ | new_arr_}_withkey
88 * ut::delete_
89 * ut::delete_arr
90 * Overloads for C++ new and delete syntax for types with extended
91 alignment:
92 * ut::aligned_new
93 * ut::aligned_new_arr
94 * ut::{aligned_new_ | aligned_new_arr_}_withkey
95 * ut::aligned_delete
96 * ut::aligned_delete_arr
97 * Custom memory allocators:
98 * ut::allocator
99 * Overloads for std::unique_ptr and std::shared_ptr factory functions
100 * ut::make_unique
101 * ut::make_unique_aligned
102 * ut::make_shared
103 * ut::make_shared_aligned
104 _withkey variants from above are the PFS-enabled dynamic allocation
105 overloads.
106
107 Usages of PFS-enabled library functions are trying to resemble already
108 familiar syntax as close as possible. For concrete examples please see
109 particular function documentation but in general it applies that ::foo(x)
110 becomes ut::foo(x) or ut::foo_withkey(key, x) where foo is some allocation
111 function listed above and key is PFS key to instrument the allocation with.
112*/
113
114#ifndef ut0new_h
115#define ut0new_h
116
117#include <algorithm>
118#include <cerrno>
119#include <cstddef>
120#include <cstdlib>
121#include <cstring>
122#include <limits>
123#include <list>
124#include <map>
125#include <memory>
126#include <set>
127#include <type_traits> /* std::is_trivially_default_constructible */
128#include <unordered_map>
129#include <unordered_set>
130
131#include "my_basename.h"
134#include "mysql/psi/psi_memory.h"
135
136namespace ut {
137/** Can be used to extract pointer and size of the allocation provided by the
138OS. It is a low level information, and is needed only to call low level
139memory-related OS functions. */
141 /** A pointer returned by the OS allocator. */
142 void *base_ptr;
143 /** The size of allocation that OS performed. */
145};
146} // namespace ut
147
148#include "detail/ut0new.h"
149#include "os0proc.h"
150#include "os0thread.h"
151#include "univ.i"
152#include "ut0byte.h" /* ut_align */
153#include "ut0cpu_cache.h"
154#include "ut0dbg.h"
155#include "ut0ut.h"
156
157namespace ut {
158
159/** Light-weight and type-safe wrapper around the PSI_memory_key
160 that eliminates the possibility of introducing silent bugs
161 through the course of implicit conversions and makes them
162 show up as compile-time errors.
163
164 Without this wrapper it was possible to say:
165 aligned_alloc_withkey(10*sizeof(int), key, 64))
166 Which would unfortunately compile just fine but it would silently
167 introduce a bug because it confuses the order of 10*sizeof(int) and
168 key input arguments. Both of them are unsigned types.
169
170 With the wrapper, aligned_alloc_withkey(10*sizeof(int), key, 64)) now
171 results with a compile-time error and the only proper way to accomplish
172 the original intent is to use PSI_memory_key_t wrapper like so:
173 aligned_alloc_withkey(PSI_memory_key_t{key}, 10*sizeof(int), 64))
174
175 Or by making use of the convenience function to create one:
176 aligned_alloc_withkey(make_psi_memory_key(key), 10*sizeof(int), 64))
177*/
180 PSI_memory_key operator()() const { return m_key; }
182};
183
184/** Convenience helper function to create type-safe representation of
185 PSI_memory_key.
186
187 @param[in] key PSI memory key to be held in type-safe PSI_memory_key_t.
188 @return PSI_memory_key_t which wraps the given PSI_memory_key
189 */
191 return PSI_memory_key_t(key);
192}
193
194} // namespace ut
195
196/** Maximum number of retries to allocate memory. */
197extern const size_t alloc_max_retries;
198
199/** Keys for registering allocations with performance schema.
200Pointers to these variables are supplied to PFS code via the pfs_info[]
201array and the PFS code initializes them via PSI_MEMORY_CALL(register_memory)().
202mem_key_other and mem_key_std are special in the following way.
203* If the caller has not provided a key and the file name of the caller is
204 unknown, then mem_key_std will be used. This happens only when called from
205 within `std` containers.
206* If the caller has not provided a key and the file name of the caller is
207 known, but is not amongst the predefined names (see ut_new_boot()) then
208 mem_key_other will be used. Generally this should not happen and if it
209 happens then that means that the list of predefined names must be extended.
210Keep this list alphabetically sorted. */
215/** Memory key for clone */
232/* Please obey alphabetical order in the definitions above. */
233
234/** Setup the internal objects needed for `ut::*_withkey()` to operate.
235This must be called before the first call to `ut::*_withkey()`. */
236void ut_new_boot();
237
238/** Setup the internal objects needed for `ut::*_withkey()` to operate.
239This must be called before the first call to `ut::*_withkey()`. This
240version of function might be called several times and it will
241simply skip all calls except the first one, during which the
242initialization will happen. */
243void ut_new_boot_safe();
244
245#ifdef UNIV_PFS_MEMORY
246
247/** List of filenames that allocate memory and are instrumented via PFS. */
248static constexpr const char *auto_event_names[] = {
249 /* Keep this list alphabetically sorted. */
250 "api0api",
251 "arch0recv",
252 "btr0btr",
253 "btr0cur",
254 "btr0load",
255 "btr0mtib",
256 "btr0pcur",
257 "btr0sea",
258 "buf0buf",
259 "buf0dblwr",
260 "buf0dump",
261 "buf0flu",
262 "buf0lru",
263 "ddl0builder",
264 "ddl0fts",
265 "ddl0impl-cursor",
266 "dict0dd",
267 "dict0dict",
268 "dict0load",
269 "dict0mem",
270 "dict0sdi",
271 "dict0stats",
272 "eval0eval",
273 "fil0fil",
274 "fil0innodb_pages_persistence",
275 "file",
276 "fsp0file",
277 "fts0ast",
278 "fts0config",
279 "fts0fts",
280 "fts0opt",
281 "fts0pars",
282 "fts0que",
283 "fts0sql",
284 "gis0sea",
285 "ha_innodb",
286 "ha_innopart",
287 "handler0alter",
288 "hash0hash",
289 "i_s",
290 "ibuf0ibuf",
291 "innorwlocktest",
292 "lexyy",
293 "lob0undo",
294 "lock0lock",
295 "log0ddl",
296 "log0log",
297 "log0recv",
298 "mem",
299 "mem0mem",
300 "memory",
301 "os0enc",
302 "os0event",
303 "os0file",
304 "page0cur",
305 "pars0lex",
306 "read0read",
307 "rem0rec",
308 "row0import",
309 "row0ins",
310 "row0log",
311 "row0mysql",
312 "row0pread",
313 "row0sel",
314 "srv0srv",
315 "srv0start",
316 "srv0tmp",
317 "sync0arr",
318 "sync0debug",
319 "sync0rw",
320 "sync0sharded_rw",
321 "sync0types",
322 "trx0i_s",
323 "trx0purge",
324 "trx0roll",
325 "trx0rseg",
326 "trx0sys",
327 "trx0trx",
328 "trx0undo",
329 "trx0undo_trunc",
330 "usr0sess",
331 "ut0link_buf",
332 "ut0list",
333 "ut0mem",
334 "ut0mpmcbq",
335 "ut0new",
336 "ut0object_cache",
337 "ut0pool",
338 "ut0rbt",
339 "ut0wqueue",
340};
341
342static constexpr size_t n_auto = UT_ARR_SIZE(auto_event_names);
345
346/** Compute whether a string begins with a given prefix, compile-time.
347@param[in] a first string, taken to be zero-terminated
348@param[in] b second string (prefix to search for)
349@param[in] b_len length in bytes of second string
350@return whether b is a prefix of a */
351constexpr bool ut_string_begins_with(const char *a, const char *b,
352 size_t b_len) {
353 for (size_t i = 0; i < b_len; ++i) {
354 if (a[i] != b[i]) {
355 return false;
356 }
357 }
358 return true;
359}
360
361/** Find the length of the filename without its file extension.
362@param[in] file filename, with extension but without directory
363@return length, in bytes */
364constexpr size_t ut_len_without_extension(const char *file) {
365 for (size_t i = 0;; ++i) {
366 if (file[i] == '\0' || file[i] == '.') {
367 return i;
368 }
369 }
370}
371
372/** Retrieve a memory key (registered with PFS), given the file name of the
373caller.
374@param[in] file portion of the filename - basename, with extension
375@param[in] len length of the filename to check for
376@return index to registered memory key or -1 if not found */
377constexpr int ut_new_get_key_by_base_file(const char *file, size_t len) {
378 for (size_t i = 0; i < n_auto; ++i) {
380 return static_cast<int>(i);
381 }
382 }
383 // do any non-constexpr thing here to fail the compilation and force
384 // the developer to update auto_event_names array
385 rand();
386 return -1;
387}
388
389/** Retrieve a memory key (registered with PFS), given the file name of
390the caller.
391@param[in] file portion of the filename - basename, with extension
392@return index to memory key or -1 if not found */
393constexpr int ut_new_get_key_by_file(const char *file) {
395}
396
397// Sending an expression through a template variable forces the compiler to
398// evaluate the expression at compile time (constexpr in itself has no such
399// guarantee, only that the compiler is allowed).
400template <int Value>
402 static constexpr int value = Value;
403};
404
405#define UT_NEW_THIS_FILE_PSI_INDEX \
406 (force_constexpr<ut_new_get_key_by_file(MY_BASENAME)>::value)
407
408#define UT_NEW_THIS_FILE_PSI_KEY \
409 (UT_NEW_THIS_FILE_PSI_INDEX == -1 \
410 ? ut::make_psi_memory_key(PSI_NOT_INSTRUMENTED) \
411 : ut::make_psi_memory_key(auto_event_keys[UT_NEW_THIS_FILE_PSI_INDEX]))
412
413#else
414
415#define UT_NEW_THIS_FILE_PSI_KEY ut::make_psi_memory_key(PSI_NOT_INSTRUMENTED)
416
417#endif /* UNIV_PFS_MEMORY */
418
419namespace ut {
420
421#ifdef HAVE_PSI_MEMORY_INTERFACE
422constexpr bool WITH_PFS_MEMORY = true;
423#else
424constexpr bool WITH_PFS_MEMORY = false;
425#endif
426
427/** Dynamically allocates storage of given size. Instruments the memory with
428 given PSI memory key in case PFS memory support is enabled.
429
430 @param[in] key PSI memory key to be used for PFS memory instrumentation.
431 @param[in] size Size of storage (in bytes) requested to be allocated.
432 @return Pointer to the allocated storage. nullptr if dynamic storage
433 allocation failed.
434
435 Example:
436 int *x = static_cast<int*>(ut::malloc_withkey(key, 10*sizeof(int)));
437 */
438inline void *malloc_withkey(PSI_memory_key_t key, std::size_t size) noexcept {
440 using malloc_impl = detail::Alloc_<impl>;
441 return malloc_impl::alloc<false>(size, key());
442}
443
444/** Dynamically allocates storage of given size.
445
446 NOTE: Given that this function will _NOT_ be instrumenting the allocation
447 through PFS, observability for particular parts of the system which want to
448 use it will be lost or in best case inaccurate. Please have a strong reason
449 to do so.
450
451 @param[in] size Size of storage (in bytes) requested to be allocated.
452 @return Pointer to the allocated storage. nullptr if dynamic storage
453 allocation failed.
454
455 Example:
456 int *x = static_cast<int*>(ut::malloc_withkey(UT_NEW_THIS_FILE_PSI_KEY,
457 10*sizeof(int)));
458 */
459inline void *malloc(std::size_t size) noexcept {
461}
462
463/** Dynamically allocates zero-initialized storage of given size. Instruments
464 the memory with given PSI memory key in case PFS memory support is enabled.
465
466 @param[in] key PSI memory key to be used for PFS memory instrumentation.
467 @param[in] size Size of storage (in bytes) requested to be allocated.
468 @return Pointer to the zero-initialized allocated storage. nullptr if
469 dynamic storage allocation failed.
470
471 Example:
472 int *x = static_cast<int*>(ut::zalloc_withkey(key, 10*sizeof(int)));
473 */
474inline void *zalloc_withkey(PSI_memory_key_t key, std::size_t size) noexcept {
476 using malloc_impl = detail::Alloc_<impl>;
477 return malloc_impl::alloc<true>(size, key());
478}
479
480/** Dynamically allocates zero-initialized storage of given size.
481
482 NOTE: Given that this function will _NOT_ be instrumenting the allocation
483 through PFS, observability for particular parts of the system which want to
484 use it will be lost or in best case inaccurate. Please have a strong reason
485 to do so.
486
487 @param[in] size Size of storage (in bytes) requested to be allocated.
488 @return Pointer to the zero-initialized allocated storage. nullptr if
489 dynamic storage allocation failed.
490
491 Example:
492 int *x = static_cast<int*>(ut::zalloc_withkey(UT_NEW_THIS_FILE_PSI_KEY,
493 10*sizeof(int)));
494 */
495inline void *zalloc(std::size_t size) noexcept {
497}
498
499/** Upsizes or downsizes already dynamically allocated storage to the new size.
500 Instruments the memory with given PSI memory key in case PFS memory support
501 is enabled.
502
503 It also supports standard realloc() semantics by:
504 * allocating size bytes of memory when passed ptr is nullptr
505 * freeing the memory pointed by ptr if passed size is 0
506
507 @param[in] key PSI memory key to be used for PFS memory instrumentation.
508 @param[in] ptr Pointer to the memory area to be reallocated.
509 @param[in] size New size of storage (in bytes) requested to be reallocated.
510 @return Pointer to the reallocated storage. nullptr if dynamic storage
511 allocation failed.
512
513 Example:
514 int *x = static_cast<int*>(ut::malloc_withkey(key, 10*sizeof(int));
515 x = static_cast<int*>(ut::realloc_withkey(key, ptr, 100*sizeof(int)));
516 */
517inline void *realloc_withkey(PSI_memory_key_t key, void *ptr,
518 std::size_t size) noexcept {
520 using malloc_impl = detail::Alloc_<impl>;
521 return malloc_impl::realloc(ptr, size, key());
522}
523
524/** Upsizes or downsizes already dynamically allocated storage to the new size.
525
526 It also supports standard realloc() semantics by:
527 * allocating size bytes of memory when passed ptr is nullptr
528 * freeing the memory pointed by ptr if passed size is 0
529
530 NOTE: Given that this function will _NOT_ be instrumenting the allocation
531 through PFS, observability for particular parts of the system which want to
532 use it will be lost or in best case inaccurate. Please have a strong reason
533 to do so.
534
535 @param[in] ptr Pointer to the memory area to be reallocated.
536 @param[in] size New size of storage (in bytes) requested to be reallocated.
537 @return Pointer to the reallocated storage. nullptr if dynamic storage
538 allocation failed.
539
540 Example:
541 int *x = static_cast<int*>(ut::malloc_withkey(UT_NEW_THIS_FILE_PSI_KEY,
542 10*sizeof(int)); x = static_cast<int*>(ut::realloc(key, ptr,
543 100*sizeof(int)));
544 */
545inline void *realloc(void *ptr, std::size_t size) noexcept {
547 size);
548}
549
550/** Releases storage which has been dynamically allocated through any of
551 the ut::malloc*(), ut::realloc* or ut::zalloc*() variants.
552
553 @param[in] ptr Pointer which has been obtained through any of the
554 ut::malloc*(), ut::realloc* or ut::zalloc*() variants.
555
556 Example:
557 ut::free(ptr);
558 */
559inline void free(void *ptr) noexcept {
561 using malloc_impl = detail::Alloc_<impl>;
563}
564
565/** Dynamically allocates storage for an object of type T. Constructs the object
566 of type T with provided Args. Instruments the memory with given PSI memory
567 key in case PFS memory support is enabled.
568
569 @param[in] key PSI memory key to be used for PFS memory instrumentation.
570 @param[in] args Arguments one wishes to pass over to T constructor(s)
571 @return Pointer to the allocated storage. Throws std::bad_alloc exception
572 if dynamic storage allocation could not be fulfilled. Re-throws whatever
573 exception that may have occurred during the construction of T, in which case
574 it automatically cleans up the raw memory allocated for it.
575
576 Example 1:
577 int *ptr = ut::new_withkey<int>(key);
578
579 Example 2:
580 int *ptr = ut::new_withkey<int>(key, 10);
581 assert(*ptr == 10);
582
583 Example 3:
584 struct A {
585 A(int x, int y) : _x(x), _y(y) {}
586 int _x, _y;
587 };
588 A *ptr = ut::new_withkey<A>(key, 1, 2);
589 assert(ptr->_x == 1);
590 assert(ptr->_y == 2);
591 */
592template <typename T, typename... Args>
593inline T *new_withkey(PSI_memory_key_t key, Args &&...args) {
594 auto mem = ut::malloc_withkey(key, sizeof(T));
595 if (unlikely(!mem)) throw std::bad_alloc();
596 try {
597 new (mem) T(std::forward<Args>(args)...);
598 } catch (...) {
599 ut::free(mem);
600 throw;
601 }
602 return static_cast<T *>(mem);
603}
604
605/** Dynamically allocates storage for an object of type T. Constructs the object
606 of type T with provided Args.
607
608 NOTE: Given that this function will _NOT_ be instrumenting the allocation
609 through PFS, observability for particular parts of the system which want to
610 use it will be lost or in best case inaccurate. Please have a strong reason
611 to do so.
612
613 @param[in] args Arguments one wishes to pass over to T constructor(s)
614 @return Pointer to the allocated storage. Throws std::bad_alloc exception
615 if dynamic storage allocation could not be fulfilled. Re-throws whatever
616 exception that may have occurred during the construction of T, in which case
617 it automatically cleans up the raw memory allocated for it.
618
619 Example 1:
620 int *ptr = ut::new_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY);
621
622 Example 2:
623 int *ptr = ut::new_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY, 10);
624 assert(*ptr == 10);
625
626 Example 3:
627 struct A {
628 A(int x, int y) : _x(x), _y(y) {}
629 int _x, _y;
630 };
631 A *ptr = ut::new_withkey<A>(UT_NEW_THIS_FILE_PSI_KEY, 1, 2);
632 assert(ptr->_x == 1);
633 assert(ptr->_y == 2);
634 */
635template <typename T, typename... Args>
636inline T *new_(Args &&...args) {
637 return ut::new_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
638 std::forward<Args>(args)...);
639}
640
641/** Releases storage which has been dynamically allocated through any of
642 the ut::new*() variants. Destructs the object of type T.
643
644 @param[in] ptr Pointer which has been obtained through any of the
645 ut::new*() variants
646
647 Example:
648 ut::delete_(ptr);
649 */
650template <typename T>
651inline void delete_(T *ptr) noexcept {
652 if (unlikely(!ptr)) return;
653 ptr->~T();
654 ut::free(ptr);
655}
656
657/** Dynamically allocates storage for an array of T's. Constructs objects of
658 type T with provided Args. Arguments that are to be used to construct some
659 respective instance of T shall be wrapped into a std::tuple. See examples
660 down below. Instruments the memory with given PSI memory key in case PFS
661 memory support is enabled.
662
663 To create an array of default-intialized T's, one can use this function
664 template but for convenience purposes one can achieve the same by using
665 the ut::new_arr_withkey with ut::Count overload.
666
667 @param[in] key PSI memory key to be used for PFS memory instrumentation.
668 @param[in] args Tuples of arguments one wishes to pass over to T
669 constructor(s).
670 @return Pointer to the first element of allocated storage. Throws
671 std::bad_alloc exception if dynamic storage allocation could not be
672 fulfilled. Re-throws whatever exception that may have occurred during the
673 construction of any instance of T, in which case it automatically destroys
674 successfully constructed objects till that moment (if any), and finally
675 cleans up the raw memory allocated for T instances.
676
677 Example 1:
678 int *ptr = ut::new_arr_withkey<int>(key,
679 std::forward_as_tuple(1),
680 std::forward_as_tuple(2));
681 assert(ptr[0] == 1);
682 assert(ptr[1] == 2);
683
684 Example 2:
685 struct A {
686 A(int x, int y) : _x(x), _y(y) {}
687 int _x, _y;
688 };
689 A *ptr = ut::new_arr_withkey<A>(key,
690 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
691 std::forward_as_tuple(4, 5), std::forward_as_tuple(6, 7),
692 std::forward_as_tuple(8, 9));
693 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
694 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
695 assert(ptr[2]->_x == 4 && ptr[2]->_y == 5);
696 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
697 assert(ptr[4]->_x == 8 && ptr[4]->_y == 9);
698
699 Example 3:
700 struct A {
701 A() : _x(10), _y(100) {}
702 A(int x, int y) : _x(x), _y(y) {}
703 int _x, _y;
704 };
705 A *ptr = ut::new_arr_withkey<A>(key,
706 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
707 std::forward_as_tuple(), std::forward_as_tuple(6, 7),
708 std::forward_as_tuple());
709 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
710 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
711 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
712 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
713 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
714 */
715template <typename T, typename... Args>
716inline T *new_arr_withkey(PSI_memory_key_t key, Args &&...args) {
718 using malloc_impl = detail::Alloc_<impl>;
719 auto mem = malloc_impl::alloc<false>(sizeof(T) * sizeof...(args), key());
720 if (unlikely(!mem)) throw std::bad_alloc();
721
722 size_t idx = 0;
723 try {
724 (...,
725 detail::construct<T>(mem, sizeof(T) * idx++, std::forward<Args>(args)));
726 } catch (...) {
727 for (size_t offset = (idx - 1) * sizeof(T); offset != 0;
728 offset -= sizeof(T)) {
729 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(mem) + offset -
730 sizeof(T))
731 ->~T();
732 }
734 throw;
735 }
736 return static_cast<T *>(mem);
737}
738
739/** Dynamically allocates storage for an array of T's. Constructs objects of
740 type T with provided Args. Arguments that are to be used to construct some
741 respective instance of T shall be wrapped into a std::tuple. See examples
742 down below.
743
744 To create an array of default-intialized T's, one can use this function
745 template but for convenience purposes one can achieve the same by using
746 the ut::new_arr_withkey with ut::Count overload.
747
748 NOTE: Given that this function will _NOT_ be instrumenting the allocation
749 through PFS, observability for particular parts of the system which want to
750 use it will be lost or in best case inaccurate. Please have a strong reason
751 to do so.
752
753 @param[in] args Tuples of arguments one wishes to pass over to T
754 constructor(s).
755 @return Pointer to the first element of allocated storage. Throws
756 std::bad_alloc exception if dynamic storage allocation could not be
757 fulfilled. Re-throws whatever exception that may have occurred during the
758 construction of any instance of T, in which case it automatically destroys
759 successfully constructed objects till that moment (if any), and finally
760 cleans up the raw memory allocated for T instances.
761
762 Example 1:
763 int *ptr = ut::new_arr_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY,
764 std::forward_as_tuple(1),
765 std::forward_as_tuple(2));
766 assert(ptr[0] == 1);
767 assert(ptr[1] == 2);
768
769 Example 2:
770 struct A {
771 A(int x, int y) : _x(x), _y(y) {}
772 int _x, _y;
773 };
774 A *ptr = ut::new_arr_withkey<A>(UT_NEW_THIS_FILE_PSI_KEY,
775 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
776 std::forward_as_tuple(4, 5), std::forward_as_tuple(6, 7),
777 std::forward_as_tuple(8, 9));
778 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
779 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
780 assert(ptr[2]->_x == 4 && ptr[2]->_y == 5);
781 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
782 assert(ptr[4]->_x == 8 && ptr[4]->_y == 9);
783
784 Example 3:
785 struct A {
786 A() : _x(10), _y(100) {}
787 A(int x, int y) : _x(x), _y(y) {}
788 int _x, _y;
789 };
790 A *ptr = ut::new_arr_withkey<A>(UT_NEW_THIS_FILE_PSI_KEY,
791 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
792 std::forward_as_tuple(), std::forward_as_tuple(6, 7),
793 std::forward_as_tuple());
794 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
795 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
796 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
797 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
798 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
799 */
800template <typename T, typename... Args>
801inline T *new_arr(Args &&...args) {
802 return ut::new_arr_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
803 std::forward<Args>(args)...);
804}
805
806/** Light-weight and type-safe wrapper which serves a purpose of
807 being able to select proper ut::new_arr* overload.
808
809 Without having a separate overload with this type, creating an array of
810 default-initialized instances of T through the ut::new_arr*(Args &&... args)
811 overload would have been impossible because:
812 int *ptr = ut::new_arr_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY, 5);
813 wouldn't even compile and
814 int *ptr = ut::new_arr_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY,
815 std::forward_as_tuple(5)); would compile but would not have intended effect.
816 It would create an array holding 1 integer element that is initialized to 5.
817
818 Given that function templates cannot be specialized, having an overload
819 crafted specifically for given case solves the problem:
820 int *ptr = ut::new_arr_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY,
821 ut::Count{5});
822*/
823struct Count {
824 explicit Count(size_t count) : m_count(count) {}
825 size_t operator()() const { return m_count; }
826 size_t m_count;
827};
828
829/** Dynamically allocates storage for an array of T's. Constructs objects of
830 type T using default constructor. If T cannot be default-initialized (e.g.
831 default constructor does not exist), then this interface cannot be used for
832 constructing such an array. ut::new_arr_withkey overload with user-provided
833 initialization must be used then. Instruments the memory with given PSI
834 memory key in case PFS memory support is enabled.
835
836 @param[in] key PSI memory key to be used for PFS memory instrumentation.
837 @param[in] count Number of T elements in an array.
838 @return Pointer to the first element of allocated storage. Throws
839 std::bad_alloc exception if dynamic storage allocation could not be
840 fulfilled. Re-throws whatever exception that may have occurred during the
841 construction of any instance of T, in which case it automatically destroys
842 successfully constructed objects till that moment (if any), and finally
843 cleans up the raw memory allocated for T instances.
844
845 Example 1:
846 int *ptr = ut::new_arr_withkey<int>(key, ut::Count{2});
847
848 Example 2:
849 struct A {
850 A() : _x(10), _y(100) {}
851 int _x, _y;
852 };
853 A *ptr = ut::new_arr_withkey<A>(key, ut::Count{5});
854 assert(ptr[0]->_x == 10 && ptr[0]->_y == 100);
855 assert(ptr[1]->_x == 10 && ptr[1]->_y == 100);
856 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
857 assert(ptr[3]->_x == 10 && ptr[3]->_y == 100);
858 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
859
860 Example 3:
861 struct A {
862 A(int x, int y) : _x(x), _y(y) {}
863 int _x, _y;
864 };
865 // Following cannot compile because A is not default-constructible
866 A *ptr = ut::new_arr_withkey<A>(key, ut::Count{5});
867 */
868template <typename T>
871 using malloc_impl = detail::Alloc_<impl>;
872 auto mem = malloc_impl::alloc<false>(sizeof(T) * count(), key());
873 if (unlikely(!mem)) throw std::bad_alloc();
874
875 size_t offset = 0;
876 try {
877 for (; offset < sizeof(T) * count(); offset += sizeof(T)) {
878 new (reinterpret_cast<uint8_t *>(mem) + offset) T{};
879 }
880 } catch (...) {
881 for (; offset != 0; offset -= sizeof(T)) {
882 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(mem) + offset -
883 sizeof(T))
884 ->~T();
885 }
887 throw;
888 }
889 return static_cast<T *>(mem);
890}
891
892/** Dynamically allocates storage for an array of T's. Constructs objects of
893 type T using default constructor. If T cannot be default-initialized (e.g.
894 default constructor does not exist), then this interface cannot be used for
895 constructing such an array. ut::new_arr overload with user-provided
896 initialization must be used then.
897
898 NOTE: Given that this function will _NOT_ be instrumenting the allocation
899 through PFS, observability for particular parts of the system which want to
900 use it will be lost or in best case inaccurate. Please have a strong reason
901 to do so.
902
903 @param[in] count Number of T elements in an array.
904 @return Pointer to the first element of allocated storage. Throws
905 std::bad_alloc exception if dynamic storage allocation could not be
906 fulfilled. Re-throws whatever exception that may have occurred during the
907 construction of any instance of T, in which case it automatically destroys
908 successfully constructed objects till that moment (if any), and finally
909 cleans up the raw memory allocated for T instances.
910
911 Example 1:
912 int *ptr = ut::new_arr_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY,
913 ut::Count{2});
914
915 Example 2:
916 struct A {
917 A() : _x(10), _y(100) {}
918 int _x, _y;
919 };
920 A *ptr = ut::new_arr_withkey<A>(UT_NEW_THIS_FILE_PSI_KEY, ut::Count{5});
921 assert(ptr[0]->_x == 10 && ptr[0]->_y == 100);
922 assert(ptr[1]->_x == 10 && ptr[1]->_y == 100);
923 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
924 assert(ptr[3]->_x == 10 && ptr[3]->_y == 100);
925 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
926
927 Example 3:
928 struct A {
929 A(int x, int y) : _x(x), _y(y) {}
930 int _x, _y;
931 };
932 // Following cannot compile because A is not default-constructible
933 A *ptr = ut::new_arr_withkey<A>(UT_NEW_THIS_FILE_PSI_KEY, ut::Count{5});
934 */
935template <typename T>
937 return ut::new_arr_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
938 count);
939}
940
941/** Releases storage which has been dynamically allocated through any of
942 the ut::new_arr*() variants. Destructs all objects of type T.
943
944 @param[in] ptr Pointer which has been obtained through any of the
945 ut::new_arr*() variants
946
947 Example:
948 ut::delete_arr(ptr);
949 */
950template <typename T>
951inline void delete_arr(T *ptr) noexcept {
952 if (unlikely(!ptr)) return;
954 using malloc_impl = detail::Alloc_<impl>;
955 const auto data_len = malloc_impl::datalen(ptr);
956 for (size_t offset = 0; offset < data_len; offset += sizeof(T)) {
957 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(ptr) + offset)->~T();
958 }
960}
961
962/** Returns number of bytes that ut::malloc_*, ut::zalloc_*, ut::realloc_* and
963 ut::new_* variants will be using to store the necessary metadata for PFS.
964
965 @return Size of the PFS metadata.
966*/
967inline size_t pfs_overhead() noexcept {
969 using malloc_impl = detail::Alloc_<impl>;
971}
972
973/** Dynamically allocates system page-aligned storage of given size. Instruments
974 the memory with given PSI memory key in case PFS memory support is enabled.
975
976 Actual page-alignment, and thus page-size, will depend on CPU architecture
977 but in general page is traditionally mostly 4K large. In contrast to Unices,
978 Windows do make an exception here and implement 64K granularity on top of
979 regular page-size for some legacy reasons. For more details see:
980 https://devblogs.microsoft.com/oldnewthing/20031008-00/?p=42223
981
982 @param[in] key PSI memory key to be used for PFS memory instrumentation.
983 @param[in] size Size of storage (in bytes) requested to be allocated.
984 @return Pointer to the page-aligned storage. nullptr if dynamic storage
985 allocation failed.
986
987 Example:
988 int *x = static_cast<int*>(ut::malloc_page_withkey(key, 10*sizeof(int)));
989 */
991 std::size_t size) noexcept {
993 using page_alloc_impl = detail::Page_alloc_<impl>;
994 return page_alloc_impl::alloc(size, key());
995}
996
997/** Dynamically allocates system page-aligned storage of given size.
998
999 Actual page-alignment, and thus page-size, will depend on CPU architecture
1000 but in general page is traditionally mostly 4K large. In contrast to Unices,
1001 Windows do make an exception here and implement 64K granularity on top of
1002 regular page-size for some legacy reasons. For more details see:
1003 https://devblogs.microsoft.com/oldnewthing/20031008-00/?p=42223
1004
1005 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1006 through PFS, observability for particular parts of the system which want to
1007 use it will be lost or in best case inaccurate. Please have a strong reason
1008 to do so.
1009
1010 @param[in] size Size of storage (in bytes) requested to be allocated.
1011 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1012 allocation failed.
1013
1014 Example:
1015 int *x = static_cast<int*>(ut::malloc_page(10*sizeof(int)));
1016 */
1017inline void *malloc_page(std::size_t size) noexcept {
1019 size);
1020}
1021
1022/** Retrieves the total amount of bytes that are available for application code
1023 to use.
1024
1025 Amount of bytes returned does _not_ have to match bytes requested
1026 through ut::malloc_page*(). This is so because bytes requested will always
1027 be implicitly rounded up to the next regular page size (e.g. 4K).
1028
1029 @param[in] ptr Pointer which has been obtained through any of the
1030 ut::malloc_page*() variants.
1031 @return Number of bytes available.
1032
1033 Example:
1034 int *x = static_cast<int*>(ut::malloc_page(10*sizeof(int)));
1035 assert(page_allocation_size(x) == CPU_PAGE_SIZE);
1036 */
1037inline size_t page_allocation_size(void *ptr) noexcept {
1039 using page_alloc_impl = detail::Page_alloc_<impl>;
1040 return page_alloc_impl::datalen(ptr);
1041}
1042
1043/** Retrieves the pointer and size of the allocation provided by the OS. It is a
1044 low level information, and is needed only to call low level memory-related
1045 OS functions.
1046
1047 @param[in] ptr Pointer which has been obtained through any of the
1048 ut::malloc_page*() variants.
1049 @return Low level OS allocation info.
1050 */
1053 using page_alloc_impl = detail::Page_alloc_<impl>;
1054 return page_alloc_impl::low_level_info(ptr);
1055}
1056
1057/** Releases storage which has been dynamically allocated through any of
1058 the ut::malloc_page*() variants.
1059
1060 @param[in] ptr Pointer which has been obtained through any of the
1061 ut::malloc_page*() variants.
1062 @return True if releasing the page-aligned memory was successful.
1063
1064 Example:
1065 ut::free_page(ptr);
1066 */
1067inline bool free_page(void *ptr) noexcept {
1069 using page_alloc_impl = detail::Page_alloc_<impl>;
1070 return page_alloc_impl::free(ptr);
1071}
1072
1073/** Dynamically allocates memory backed up by large (huge) pages. Instruments
1074 the memory with given PSI memory key in case PFS memory support is enabled.
1075
1076 For large (huge) pages to be functional, usually some steps in system admin
1077 preparation is required. Exact steps vary from system to system.
1078
1079 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1080 @param[in] size Size of storage (in bytes) requested to be allocated.
1081 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1082 allocation failed.
1083
1084 Example:
1085 int *x = static_cast<int*>(
1086 ut::malloc_large_page_withkey(key, 10*sizeof(int))
1087 );
1088 */
1090 std::size_t size) noexcept {
1092 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1093 return large_page_alloc_impl::alloc(size, key());
1094}
1095
1096/** Dynamically allocates memory backed up by large (huge) pages.
1097
1098 For large (huge) pages to be functional, usually some steps in system admin
1099 preparation is required. Exact steps vary from system to system.
1100
1101 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1102 through PFS, observability for particular parts of the system which want to
1103 use it will be lost or in best case inaccurate. Please have a strong reason
1104 to do so.
1105
1106 @param[in] size Size of storage (in bytes) requested to be allocated.
1107 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1108 allocation failed.
1109
1110 Example:
1111 int *x = static_cast<int*>(ut::malloc_large_page(10*sizeof(int)));
1112 */
1113inline void *malloc_large_page(std::size_t size) noexcept {
1116}
1117
1118/** Retrieves the total amount of bytes that are available for application code
1119 to use.
1120
1121 Amount of bytes returned does _not_ have to match bytes requested
1122 through ut::malloc_large_page*(). This is so because bytes requested will
1123 always be implicitly rounded up to the next multiple of huge-page size (e.g.
1124 2MiB). Exact huge-page size value that is going to be used will be stored
1125 in large_page_default_size.
1126
1127 @param[in] ptr Pointer which has been obtained through any of the
1128 ut::malloc_large_page*() variants.
1129 @return Number of bytes available.
1130
1131 Example:
1132 int *x = static_cast<int*>(ut::malloc_large_page(10*sizeof(int)));
1133 assert(large_page_allocation_size(x) == HUGE_PAGE_SIZE);
1134 */
1135inline size_t large_page_allocation_size(void *ptr) noexcept {
1137 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1138 return large_page_alloc_impl::datalen(ptr);
1139}
1140
1141/** Retrieves the pointer and size of the allocation provided by the OS. It is a
1142 low level information, and is needed only to call low level memory-related
1143 OS functions.
1144
1145 @param[in] ptr Pointer which has been obtained through any of the
1146 ut::malloc_large_page*() variants.
1147 @return Low level OS allocation info.
1148 */
1151 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1152 return large_page_alloc_impl::low_level_info(ptr);
1153}
1154
1155/** Releases storage which has been dynamically allocated through any of
1156 the ut::malloc_large_page*() variants.
1157
1158 @param[in] ptr Pointer which has been obtained through any of the
1159 ut::malloc_large_page*() variants.
1160 @return True if releasing the large (huge) page-aligned memory was
1161 successful.
1162
1163 Example:
1164 ut::free_large_page(ptr);
1165 */
1166inline bool free_large_page(void *ptr) noexcept {
1168 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1169 return large_page_alloc_impl::free(ptr);
1170}
1171
1172/* Helper type for tag-dispatch */
1174
1175/** Dynamically allocates memory backed up by large (huge) pages. In the event
1176 that large (huge) pages are unavailable or disabled explicitly through
1177 os_use_large_pages, it will fallback to dynamic allocation backed by
1178 page-aligned memory. Instruments the memory with given PSI memory key in
1179 case PFS memory support is enabled.
1180
1181 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1182 @param[in] size Size of storage (in bytes) requested to be allocated.
1183 @param[in] large_pages_enabled If true, the large pages will be tried to be
1184 used.
1185 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1186 allocation failed.
1187
1188 Example:
1189 int *x = static_cast<int*>(
1190 ut::malloc_large_page_withkey(
1191 key,
1192 10*sizeof(int),
1193 fallback_to_normal_page_t{}
1194 )
1195 );
1196 */
1199 bool large_pages_enabled = os_use_large_pages) noexcept {
1200 void *large_page_mem = nullptr;
1201 if (large_pages_enabled) {
1202 large_page_mem = malloc_large_page_withkey(key, size);
1203 }
1204 return large_page_mem ? large_page_mem : malloc_page_withkey(key, size);
1205}
1206
1207/** Dynamically allocates memory backed up by large (huge) pages. In the event
1208 that large (huge) pages are unavailable or disabled explicitly through
1209 os_use_large_pages, it will fallback to dynamic allocation backed by
1210 page-aligned memory.
1211
1212 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1213 through PFS, observability for particular parts of the system which want to
1214 use it will be lost or in best case inaccurate. Please have a strong reason
1215 to do so.
1216
1217 @param[in] size Size of storage (in bytes) requested to be allocated.
1218 @param[in] large_pages_enabled If true, the large pages will be tried to be
1219 used.
1220 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1221 allocation failed.
1222
1223 Example:
1224 int *x = static_cast<int*>(
1225 ut::malloc_large_page(
1226 10*sizeof(int),
1227 fallback_to_normal_page_t{}
1228 )
1229 );
1230 */
1232 std::size_t size, fallback_to_normal_page_t,
1233 bool large_pages_enabled = os_use_large_pages) noexcept {
1236 fallback_to_normal_page_t{}, large_pages_enabled);
1237}
1238
1239/** Retrieves the total amount of bytes that are available for application code
1240 to use.
1241
1242 Amount of bytes returned does _not_ have to match bytes requested
1243 through ut::malloc_large_page*(fallback_to_normal_page_t). This is so
1244 because bytes requested will always be implicitly rounded up to the next
1245 multiple of either huge-page size (e.g. 2MiB) or regular page size (e.g.
1246 4K).
1247
1248 @param[in] ptr Pointer which has been obtained through any of the
1249 ut::malloc_large_page*(fallback_to_normal_page_t) variants.
1250 @return Number of bytes available for use.
1251 */
1252inline size_t large_page_allocation_size(void *ptr,
1253 fallback_to_normal_page_t) noexcept {
1254 assert(ptr);
1256 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1257 if (large_page_alloc_impl::page_type(ptr) == detail::Page_type::system_page)
1258 return ut::page_allocation_size(ptr);
1259 ut_a(large_page_alloc_impl::page_type(ptr) == detail::Page_type::large_page);
1261}
1262
1263/** Retrieves the pointer and size of the allocation provided by the OS. It is a
1264 low level information, and is needed only to call low level memory-related
1265 OS functions.
1266
1267 @param[in] ptr Pointer which has been obtained through any of the
1268 ut::malloc_large_page*(fallback_to_normal_page_t) variants.
1269 @return Low level OS allocation info.
1270 */
1272 void *ptr, fallback_to_normal_page_t) noexcept {
1273 assert(ptr);
1275 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1276 if (large_page_alloc_impl::page_type(ptr) == detail::Page_type::system_page)
1277 return ut::page_low_level_info(ptr);
1278 ut_a(large_page_alloc_impl::page_type(ptr) == detail::Page_type::large_page);
1280}
1281
1282/** Releases storage which has been dynamically allocated through any of
1283 the ut::malloc_large_page*(fallback_to_normal_page_t) variants.
1284
1285 Whether the pointer is representing area backed up by regular or huge-pages,
1286 this function will know the difference and therefore act accordingly.
1287
1288 @param[in] ptr Pointer which has been obtained through any of the
1289 ut::malloc_large_page*(fallback_to_normal_page_t) variants.
1290 @return True if releasing the memory was successful.
1291
1292 Example:
1293 ut::free_large_page(ptr);
1294 */
1295inline bool free_large_page(void *ptr, fallback_to_normal_page_t) noexcept {
1297 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1298
1299 if (!ptr) return false;
1300
1301 bool success;
1302 if (large_page_alloc_impl::page_type(ptr) == detail::Page_type::system_page) {
1303 success = free_page(ptr);
1304 } else {
1305 ut_a(large_page_alloc_impl::page_type(ptr) ==
1307 success = free_large_page(ptr);
1308 }
1309 assert(success);
1310 return success;
1311}
1312
1313/** Dynamically allocates storage of given size and at the address aligned to
1314 the requested alignment. Instruments the memory with given PSI memory key
1315 in case PFS memory support is enabled.
1316
1317 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1318 @param[in] size Size of storage (in bytes) requested to be allocated.
1319 @param[in] alignment Alignment requirement for storage to be allocated.
1320 @return Pointer to the allocated storage. nullptr if dynamic storage
1321 allocation failed.
1322
1323 Example:
1324 int* x = static_cast<int*>(aligned_alloc_withkey(key, 10*sizeof(int), 64));
1325 */
1327 std::size_t alignment) noexcept {
1329 using aligned_alloc_impl = detail::Aligned_alloc_<impl>;
1330 return aligned_alloc_impl::alloc<false>(size, alignment, key());
1331}
1332
1333/** Dynamically allocates storage of given size and at the address aligned to
1334 the requested alignment.
1335
1336 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1337 through PFS, observability for particular parts of the system which want to
1338 use it will be lost or in best case inaccurate. Please have a strong reason
1339 to do so.
1340
1341 @param[in] size Size of storage (in bytes) requested to be allocated.
1342 @param[in] alignment Alignment requirement for storage to be allocated.
1343 @return Pointer to the allocated storage. nullptr if dynamic storage
1344 allocation failed.
1345
1346 Example:
1347 int* x = static_cast<int*>(aligned_alloc(10*sizeof(int), 64));
1348 */
1349inline void *aligned_alloc(std::size_t size, std::size_t alignment) noexcept {
1351 alignment);
1352}
1353
1354/** Dynamically allocates zero-initialized storage of given size and at the
1355 address aligned to the requested alignment. Instruments the memory with
1356 given PSI memory key in case PFS memory support is enabled.
1357
1358 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1359 @param[in] size Size of storage (in bytes) requested to be allocated.
1360 @param[in] alignment Alignment requirement for storage to be allocated.
1361 @return Pointer to the zero-initialized allocated storage. nullptr if
1362 dynamic storage allocation failed.
1363
1364 Example:
1365 int* x =
1366 static_cast<int*>(aligned_zalloc_withkey(key, 10*sizeof(int), 64));
1367 */
1369 std::size_t alignment) noexcept {
1371 using aligned_alloc_impl = detail::Aligned_alloc_<impl>;
1372 return aligned_alloc_impl::alloc<true>(size, alignment, key());
1373}
1374
1375/** Dynamically allocates zero-initialized storage of given size and at the
1376 address aligned to the requested alignment.
1377
1378 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1379 through PFS, observability for particular parts of the system which want to
1380 use it will be lost or in best case inaccurate. Please have a strong reason
1381 to do so.
1382
1383 @param[in] size Size of storage (in bytes) requested to be allocated.
1384 @param[in] alignment Alignment requirement for storage to be allocated.
1385 @return Pointer to the zero-initialized allocated storage. nullptr if
1386 dynamic storage allocation failed.
1387
1388 Example:
1389 int* x = static_cast<int*>(aligned_zalloc(10*sizeof(int), 64));
1390 */
1391inline void *aligned_zalloc(std::size_t size, std::size_t alignment) noexcept {
1393 alignment);
1394}
1395
1396/** Releases storage which has been dynamically allocated through any of
1397 the aligned_alloc_*() or aligned_zalloc_*() variants.
1398
1399 @param[in] ptr Pointer which has been obtained through any of the
1400 aligned_alloc_*() or aligned_zalloc_*() variants.
1401
1402 Example:
1403 aligned_free(ptr);
1404 */
1405inline void aligned_free(void *ptr) noexcept {
1407 using aligned_alloc_impl = detail::Aligned_alloc_<impl>;
1409}
1410
1411/** Dynamically allocates storage for an object of type T at address aligned
1412 to the requested alignment. Constructs the object of type T with provided
1413 Args. Instruments the memory with given PSI memory key in case PFS memory
1414 support is enabled.
1415
1416 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1417 @param[in] alignment Alignment requirement for storage to be allocated.
1418 @param[in] args Arguments one wishes to pass over to T constructor(s)
1419 @return Pointer to the allocated storage. Throws std::bad_alloc exception
1420 if dynamic storage allocation could not be fulfilled.
1421
1422 Example 1:
1423 int *ptr = aligned_new_withkey<int>(key, 2);
1424
1425 Example 2:
1426 int *ptr = aligned_new_withkey<int>(key, 2, 10);
1427 assert(*ptr == 10);
1428
1429 Example 3:
1430 struct A { A(int x, int y) : _x(x), _y(y) {} int x, y; }
1431 A *ptr = aligned_new_withkey<A>(key, 2, 1, 2);
1432 assert(ptr->x == 1);
1433 assert(ptr->y == 2);
1434 */
1435template <typename T, typename... Args>
1436inline T *aligned_new_withkey(PSI_memory_key_t key, std::size_t alignment,
1437 Args &&...args) {
1438 auto mem = aligned_alloc_withkey(key, sizeof(T), alignment);
1439 if (unlikely(!mem)) throw std::bad_alloc();
1440 try {
1441 new (mem) T(std::forward<Args>(args)...);
1442 } catch (...) {
1444 throw;
1445 }
1446 return static_cast<T *>(mem);
1447}
1448
1449/** Dynamically allocates storage for an object of type T at address aligned
1450 to the requested alignment. Constructs the object of type T with provided
1451 Args.
1452
1453 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1454 through PFS, observability for particular parts of the system which want to
1455 use it will be lost or in best case inaccurate. Please have a strong reason
1456 to do so.
1457
1458 @param[in] alignment Alignment requirement for storage to be allocated.
1459 @param[in] args Arguments one wishes to pass over to T constructor(s)
1460 @return Pointer to the allocated storage. Throws std::bad_alloc exception
1461 if dynamic storage allocation could not be fulfilled.
1462
1463 Example 1:
1464 int *ptr = aligned_new<int>(2);
1465
1466 Example 2:
1467 int *ptr = aligned_new<int>(2, 10);
1468 assert(*ptr == 10);
1469
1470 Example 3:
1471 struct A { A(int x, int y) : _x(x), _y(y) {} int x, y; }
1472 A *ptr = aligned_new<A>(2, 1, 2);
1473 assert(ptr->x == 1);
1474 assert(ptr->y == 2);
1475 */
1476template <typename T, typename... Args>
1477inline T *aligned_new(std::size_t alignment, Args &&...args) {
1478 return aligned_new_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
1479 alignment, std::forward<Args>(args)...);
1480}
1481
1482/** Releases storage which has been dynamically allocated through any of
1483 the aligned_new_*() variants. Destructs the object of type T.
1484
1485 @param[in] ptr Pointer which has been obtained through any of the
1486 aligned_new_*() variants
1487
1488 Example:
1489 aligned_delete(ptr);
1490 */
1491template <typename T>
1492inline void aligned_delete(T *ptr) noexcept {
1493 ptr->~T();
1494 aligned_free(ptr);
1495}
1496
1497/** Dynamically allocates storage for an array of T's at address aligned to the
1498 requested alignment. Constructs objects of type T with provided Args.
1499 Arguments that are to be used to construct some respective instance of T
1500 shall be wrapped into a std::tuple. See examples down below. Instruments the
1501 memory with given PSI memory key in case PFS memory support is enabled.
1502
1503 To create an array of default-initialized T's, one can use this function
1504 template but for convenience purposes one can achieve the same by using
1505 the ut::aligned_new_arr_withkey with ut::Count overload.
1506
1507 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1508 @param[in] alignment Alignment requirement for storage to be allocated.
1509 @param[in] args Tuples of arguments one wishes to pass over to T
1510 constructor(s).
1511 @return Pointer to the first element of allocated storage. Throws
1512 std::bad_alloc exception if dynamic storage allocation could not be
1513 fulfilled. Re-throws whatever exception that may have occurred during the
1514 construction of any instance of T, in which case it automatically destroys
1515 successfully constructed objects till that moment (if any), and finally
1516 cleans up the raw memory allocated for T instances.
1517
1518 Example 1:
1519 int *ptr = ut::aligned_new_arr_withkey<int>(key, 32,
1520 std::forward_as_tuple(1),
1521 std::forward_as_tuple(2));
1522 assert(ptr[0] == 1);
1523 assert(ptr[1] == 2);
1524
1525 Example 2:
1526 struct A {
1527 A(int x, int y) : _x(x), _y(y) {}
1528 int _x, _y;
1529 };
1530 A *ptr = ut::aligned_new_arr_withkey<A>(key, 32,
1531 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
1532 std::forward_as_tuple(4, 5), std::forward_as_tuple(6, 7),
1533 std::forward_as_tuple(8, 9));
1534 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
1535 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
1536 assert(ptr[2]->_x == 4 && ptr[2]->_y == 5);
1537 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
1538 assert(ptr[4]->_x == 8 && ptr[4]->_y == 9);
1539
1540 Example 3:
1541 struct A {
1542 A() : _x(10), _y(100) {}
1543 A(int x, int y) : _x(x), _y(y) {}
1544 int _x, _y;
1545 };
1546 A *ptr = ut::aligned_new_arr_withkey<A>(key, 32,
1547 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
1548 std::forward_as_tuple(), std::forward_as_tuple(6, 7),
1549 std::forward_as_tuple());
1550 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
1551 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
1552 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
1553 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
1554 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
1555 */
1556template <typename T, typename... Args>
1557inline T *aligned_new_arr_withkey(PSI_memory_key_t key, std::size_t alignment,
1558 Args &&...args) {
1559 auto mem = aligned_alloc_withkey(key, sizeof(T) * sizeof...(args), alignment);
1560 if (unlikely(!mem)) throw std::bad_alloc();
1561
1562 size_t idx = 0;
1563 try {
1564 (...,
1565 detail::construct<T>(mem, sizeof(T) * idx++, std::forward<Args>(args)));
1566 } catch (...) {
1567 for (size_t offset = (idx - 1) * sizeof(T); offset != 0;
1568 offset -= sizeof(T)) {
1569 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(mem) + offset -
1570 sizeof(T))
1571 ->~T();
1572 }
1574 throw;
1575 }
1576 return static_cast<T *>(mem);
1577}
1578
1579/** Dynamically allocates storage for an array of T's at address aligned to the
1580 requested alignment. Constructs objects of type T using default constructor.
1581 If T cannot be default-initialized (e.g. default constructor does not
1582 exist), then this interface cannot be used for constructing such an array.
1583 ut::new_arr_withkey overload with user-provided initialization must be used
1584 then. Instruments the memory with given PSI memory key in case PFS memory
1585 support is enabled.
1586
1587 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1588 @param[in] alignment Alignment requirement for storage to be allocated.
1589 @param[in] count Number of T elements in an array.
1590 @return Pointer to the first element of allocated storage. Throws
1591 std::bad_alloc exception if dynamic storage allocation could not be
1592 fulfilled. Re-throws whatever exception that may have occurred during the
1593 construction of any instance of T, in which case it automatically destroys
1594 successfully constructed objects till that moment (if any), and finally
1595 cleans up the raw memory allocated for T instances.
1596
1597 Example 1:
1598 int *ptr = ut::aligned_new_arr_withkey<int>(key, 32, ut::Count{2});
1599
1600 Example 2:
1601 struct A {
1602 A() : _x(10), _y(100) {}
1603 int _x, _y;
1604 };
1605 A *ptr = ut::aligned_new_arr_withkey<A>(key, 32, ut::Count{5});
1606 assert(ptr[0]->_x == 10 && ptr[0]->_y == 100);
1607 assert(ptr[1]->_x == 10 && ptr[1]->_y == 100);
1608 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
1609 assert(ptr[3]->_x == 10 && ptr[3]->_y == 100);
1610 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
1611
1612 Example 3:
1613 struct A {
1614 A(int x, int y) : _x(x), _y(y) {}
1615 int _x, _y;
1616 };
1617 // Following cannot compile because A is not default-constructible
1618 A *ptr = ut::aligned_new_arr_withkey<A>(key, 32, ut::Count{5});
1619 */
1620template <typename T>
1621inline T *aligned_new_arr_withkey(PSI_memory_key_t key, std::size_t alignment,
1622 Count count) {
1623 auto mem = aligned_alloc_withkey(key, sizeof(T) * count(), alignment);
1624 if (unlikely(!mem)) throw std::bad_alloc();
1625
1626 size_t offset = 0;
1627 try {
1628 for (; offset < sizeof(T) * count(); offset += sizeof(T)) {
1629 new (reinterpret_cast<uint8_t *>(mem) + offset) T{};
1630 }
1631 } catch (...) {
1632 for (; offset != 0; offset -= sizeof(T)) {
1633 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(mem) + offset -
1634 sizeof(T))
1635 ->~T();
1636 }
1638 throw;
1639 }
1640 return static_cast<T *>(mem);
1641}
1642
1643/** Dynamically allocates storage for an array of T's at address aligned to
1644 the requested alignment. Constructs objects of type T with provided Args.
1645
1646 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1647 through PFS, observability for particular parts of the system which want to
1648 use it will be lost or in best case inaccurate. Please have a strong reason
1649 to do so.
1650
1651 @param[in] alignment Alignment requirement for storage to be allocated.
1652 @param[in] args Arguments one wishes to pass over to T constructor(s)
1653 @return Pointer to the first element of allocated storage. Throws
1654 std::bad_alloc exception if dynamic storage allocation could not be
1655 fulfilled.
1656
1657 Example 1:
1658 int *ptr = aligned_new_arr<int, 5>(2);
1659 ptr[0] ... ptr[4]
1660
1661 Example 2:
1662 int *ptr = aligned_new_arr<int, 5>(2, 1, 2, 3, 4, 5);
1663 assert(*ptr[0] == 1);
1664 assert(*ptr[1] == 2);
1665 ...
1666 assert(*ptr[4] == 5);
1667
1668 Example 3:
1669 struct A { A(int x, int y) : _x(x), _y(y) {} int x, y; }
1670 A *ptr = aligned_new_arr<A, 5>(2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
1671 assert(ptr[0]->x == 1);
1672 assert(ptr[0]->y == 2);
1673 assert(ptr[1]->x == 3);
1674 assert(ptr[1]->y == 4);
1675 ...
1676 assert(ptr[4]->x == 9);
1677 assert(ptr[4]->y == 10);
1678 */
1679template <typename T, typename... Args>
1680inline T *aligned_new_arr(std::size_t alignment, Args &&...args) {
1681 return aligned_new_arr_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
1682 alignment, std::forward<Args>(args)...);
1683}
1684
1685/** Dynamically allocates storage for an array of T's at address aligned to
1686 the requested alignment. Constructs objects of type T using default
1687 constructor.
1688
1689 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1690 through PFS, observability for particular parts of the system which want to
1691 use it will be lost or in best case inaccurate. Please have a strong reason
1692 to do so.
1693
1694 @param[in] alignment Alignment requirement for storage to be allocated.
1695 @param[in] count Number of T elements in an array.
1696 @return Pointer to the first element of allocated storage. Throws
1697 std::bad_alloc exception if dynamic storage allocation could not be
1698 fulfilled.
1699
1700 Example 1:
1701 int *ptr = aligned_new_arr<int>(2, 5);
1702 assert(*ptr[0] == 0);
1703 assert(*ptr[1] == 0);
1704 ...
1705 assert(*ptr[4] == 0);
1706
1707 Example 2:
1708 struct A { A) : x(1), y(2) {} int x, y; }
1709 A *ptr = aligned_new_arr<A>(2, 5);
1710 assert(ptr[0].x == 1);
1711 assert(ptr[0].y == 2);
1712 ...
1713 assert(ptr[4].x == 1);
1714 assert(ptr[4].y == 2);
1715
1716 Example 3:
1717 struct A { A(int x, int y) : _x(x), _y(y) {} int x, y; }
1718 A *ptr = aligned_new_arr<A>(2, 5);
1719 // will not compile, no default constructor
1720 */
1721template <typename T>
1722inline T *aligned_new_arr(std::size_t alignment, Count count) {
1723 return aligned_new_arr_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
1724 alignment, count);
1725}
1726
1727/** Releases storage which has been dynamically allocated through any of the
1728 aligned_new_arr_*() variants. Destructs all objects of type T.
1729
1730 @param[in] ptr Pointer which has been obtained through any of the
1731 aligned_new_arr_*() variants.
1732
1733 Example:
1734 aligned_delete_arr(ptr);
1735 */
1736template <typename T>
1737inline void aligned_delete_arr(T *ptr) noexcept {
1739 using aligned_alloc_impl = detail::Aligned_alloc_<impl>;
1740 const auto data_len = aligned_alloc_impl::datalen(ptr);
1741 for (size_t offset = 0; offset < data_len; offset += sizeof(T)) {
1742 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(ptr) + offset)->~T();
1743 }
1744 aligned_free(ptr);
1745}
1746
1747/** Lightweight convenience wrapper which manages dynamically allocated
1748 over-aligned type. Wrapper makes use of RAII to do the resource cleanup.
1749
1750 Example usage:
1751 struct My_fancy_type {
1752 My_fancy_type(int x, int y) : _x(x), _y(y) {}
1753 int _x, _y;
1754 };
1755
1756 aligned_pointer<My_fancy_type, 32> ptr;
1757 ptr.alloc(10, 5);
1758 My_fancy_type *p = ptr;
1759 assert(p->_x == 10 && p->_y == 5);
1760
1761 @tparam T Type to be managed.
1762 @tparam Alignment Number of bytes to align the type T to.
1763 */
1764template <typename T, size_t Alignment>
1766 T *ptr = nullptr;
1767
1768 public:
1769 /** Destructor. Invokes destructor of the underlying instance of
1770 type T. Releases dynamically allocated resources, if there had been
1771 left any.
1772 */
1774 if (ptr) dealloc();
1775 }
1776
1777 /** Allocates sufficiently large memory of dynamic storage duration to fit
1778 the instance of type T at the address which is aligned to Alignment bytes.
1779 Constructs the instance of type T with given Args.
1780
1781 Underlying instance of type T is accessed through the conversion operator.
1782
1783 @param[in] args Any number and type of arguments that type T can be
1784 constructed with.
1785 */
1786 template <typename... Args>
1787 void alloc(Args &&...args) {
1788 ut_ad(ptr == nullptr);
1789 ptr = ut::aligned_new<T>(Alignment, args...);
1790 }
1791
1792 /** Allocates sufficiently large memory of dynamic storage duration to fit
1793 the instance of type T at the address which is aligned to Alignment bytes.
1794 Constructs the instance of type T with given Args. Instruments the memory
1795 with given PSI memory key in case PFS memory support is enabled.
1796
1797 Underlying instance of type T is accessed through the conversion operator.
1798
1799 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1800 @param[in] args Any number and type of arguments that type T can be
1801 constructed with.
1802 */
1803 template <typename... Args>
1804 void alloc_withkey(PSI_memory_key_t key, Args &&...args) {
1805 ut_ad(ptr == nullptr);
1806 ptr =
1807 ut::aligned_new_withkey<T>(key, Alignment, std::forward<Args>(args)...);
1808 }
1809
1810 /** Invokes the destructor of instance of type T, if applicable.
1811 Releases the resources previously allocated with alloc().
1812 */
1813 void dealloc() {
1814 ut_ad(ptr != nullptr);
1816 ptr = nullptr;
1817 }
1818
1819 /** Conversion operator. Used for accessing the underlying instance of
1820 type T.
1821 */
1822 operator T *() const {
1823 ut_ad(ptr != nullptr);
1824 return ptr;
1825 }
1826};
1827
1828/** Lightweight convenience wrapper which manages a dynamically
1829 allocated array of over-aligned types. Only the first element of an array is
1830 guaranteed to be aligned to the requested Alignment. Wrapper makes use of
1831 RAII to do the resource cleanup.
1832
1833 Example usage 1:
1834 struct My_fancy_type {
1835 My_fancy_type() : _x(0), _y(0) {}
1836 My_fancy_type(int x, int y) : _x(x), _y(y) {}
1837 int _x, _y;
1838 };
1839
1840 aligned_array_pointer<My_fancy_type, 32> ptr;
1841 ptr.alloc(3);
1842 My_fancy_type *p = ptr;
1843 assert(p[0]._x == 0 && p[0]._y == 0);
1844 assert(p[1]._x == 0 && p[1]._y == 0);
1845 assert(p[2]._x == 0 && p[2]._y == 0);
1846
1847 Example usage 2:
1848 aligned_array_pointer<My_fancy_type, 32> ptr;
1849 ptr.alloc<3>(1, 2, 3, 4, 5, 6);
1850 My_fancy_type *p = ptr;
1851 assert(p[0]._x == 1 && p[0]._y == 2);
1852 assert(p[1]._x == 3 && p[1]._y == 4);
1853 assert(p[2]._x == 5 && p[2]._y == 6);
1854
1855 @tparam T Type to be managed.
1856 @tparam Alignment Number of bytes to align the first element of array to.
1857 */
1858template <typename T, size_t Alignment>
1860 T *ptr = nullptr;
1861
1862 public:
1863 /** Destructor. Invokes destructors of the underlying instances of
1864 type T. Releases dynamically allocated resources, if there had been
1865 left any.
1866 */
1868 if (ptr) dealloc();
1869 }
1870
1871 /** Allocates sufficiently large memory of dynamic storage duration to fit
1872 the array of size number of elements of type T at the address which is
1873 aligned to Alignment bytes. Constructs the size number of instances of
1874 type T, each being initialized through the means of default constructor.
1875
1876 Underlying instances of type T are accessed through the conversion
1877 operator.
1878
1879 @param[in] count Number of T elements in an array.
1880 */
1882 ut_ad(ptr == nullptr);
1883 ptr = ut::aligned_new_arr<T>(Alignment, count);
1884 }
1885
1886 /** Allocates sufficiently large memory of dynamic storage duration to fit
1887 the array of size number of elements of type T at the address which is
1888 aligned to Alignment bytes. Constructs the size number of instances of
1889 type T, each being initialized through the means of provided Args and
1890 corresponding constructors.
1891
1892 Underlying instances of type T are accessed through the conversion
1893 operator.
1894
1895 @param[in] args Any number and type of arguments that type T can be
1896 constructed with.
1897 */
1898 template <typename... Args>
1899 void alloc(Args &&...args) {
1900 ut_ad(ptr == nullptr);
1901 ptr = ut::aligned_new_arr<T>(Alignment, std::forward<Args>(args)...);
1902 }
1903
1904 /** Allocates sufficiently large memory of dynamic storage duration to fit
1905 the array of size number of elements of type T at the address which is
1906 aligned to Alignment bytes. Constructs the size number of instances of
1907 type T, each being initialized through the means of default constructor.
1908 Instruments the memory with given PSI memory key in case PFS memory
1909 support is enabled.
1910
1911 Underlying instances of type T are accessed through the conversion
1912 operator.
1913
1914 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1915 @param[in] count Number of T elements in an array.
1916 */
1918 ut_ad(ptr == nullptr);
1919 ptr = ut::aligned_new_arr_withkey<T>(key, Alignment, count);
1920 }
1921
1922 /** Allocates sufficiently large memory of dynamic storage duration to fit
1923 the array of size number of elements of type T at the address which is
1924 aligned to Alignment bytes. Constructs the size number of instances of
1925 type T, each being initialized through the means of provided Args and
1926 corresponding constructors. Instruments the memory with given PSI memory
1927 key in case PFS memory support is enabled.
1928
1929 Underlying instances of type T are accessed through the conversion
1930 operator.
1931
1932 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1933 @param[in] args Any number and type of arguments that type T can be
1934 constructed with.
1935 */
1936 template <typename... Args>
1937 void alloc_withkey(PSI_memory_key_t key, Args &&...args) {
1938 ut_ad(ptr == nullptr);
1939 ptr = ut::aligned_new_arr_withkey<T>(key, Alignment,
1940 std::forward<Args>(args)...);
1941 }
1942
1943 /** Invokes destructors of instances of type T, if applicable.
1944 Releases the resources previously allocated with any variant of
1945 alloc().
1946 */
1947 void dealloc() {
1949 ptr = nullptr;
1950 }
1951
1952 /** Conversion operator. Used for accessing the underlying instances of
1953 type T.
1954 */
1955 operator T *() const {
1956 ut_ad(ptr != nullptr);
1957 return ptr;
1958 }
1959};
1960
1961namespace detail {
1962template <typename T>
1964 explicit allocator_base(PSI_memory_key /*key*/) {}
1965
1966 template <typename U>
1967 allocator_base(const allocator_base<U> & /*other*/) {}
1968
1969 void *allocate_impl(size_t n_bytes) { return ut::malloc(n_bytes); }
1970};
1971
1972template <typename T>
1975
1976 template <typename U>
1978 : allocator_base_pfs(other.get_mem_key()) {}
1979
1981
1982 void *allocate_impl(size_t n_bytes) {
1984 }
1985
1986 private:
1988};
1989} // namespace detail
1990
1991/** Allocator that allows `std` containers to manage their memory through
1992 ut::malloc* and ut::free library functions.
1993
1994 Main purpose of this custom allocator is to instrument all of the memory
1995 allocations and deallocations that are being done by `std` containers under
1996 the hood, and have them recorded through the PFS (memory) engine.
1997
1998 Other than `std` containers, this allocator is of course also suitable for
1999 use in any other allocator-aware containers and/or code.
2000
2001 Given that `ut::malloc*` and ut::free library functions already handle all
2002 the PFS and non-PFS implementation bits and pieces, this allocator is a mere
2003 wrapper around them.
2004
2005 Example which uses default PFS key (mem_key_std) to trace all std::vector
2006 allocations and deallocations:
2007 std::vector<int, ut::allocator<int>> vec;
2008 vec.push_back(...);
2009 ...
2010 vec.push_back(...);
2011
2012 Example which uses user-provided PFS key to trace std::vector allocations
2013 and deallocations:
2014 ut::allocator<int> allocator(some_other_psi_key);
2015 std::vector<int, ut::allocator<int>> vec(allocator);
2016 vec.push_back(...);
2017 ...
2018 vec.push_back(...);
2019 */
2020template <typename T, typename Allocator_base = std::conditional_t<
2023class allocator : public Allocator_base {
2024 public:
2025 using pointer = T *;
2026 using const_pointer = const T *;
2027 using reference = T &;
2028 using const_reference = const T &;
2029 using value_type = T;
2030 using size_type = size_t;
2031 using difference_type = ptrdiff_t;
2032
2033 static_assert(alignof(T) <= alignof(std::max_align_t),
2034 "ut::allocator does not support over-aligned types. Use "
2035 "ut::aligned_* API to handle such types.");
2036
2037 /** Default constructor, use mem_key_std.
2038 */
2039 allocator() : Allocator_base(mem_key_std) {}
2040
2041 /** Explicit constructor.
2042 @param[in] key performance schema key.
2043 */
2044 explicit allocator(PSI_memory_key key) : Allocator_base(key) {}
2045
2046 /* Rule-of-five */
2049 const allocator<T, Allocator_base> &) = default;
2052 default;
2053 ~allocator() = default;
2054
2055 /** Copy-construct a new instance of allocator with type T by using existing
2056 instance of allocator constructed with a different type U.
2057 @param[in] other the allocator to copy from.
2058 */
2059 template <typename U>
2061 : Allocator_base(other) {}
2062
2063 /* NOTE: rebind is deprecated in C++17 and to be removed in C++20 but one of
2064 our toolchains, when used in 32-bit setting, still does not support custom
2065 allocators that do not provide rebind support explicitly. In future, this
2066 part will become redundant and can be removed.
2067 */
2068 template <typename U>
2069 struct rebind {
2071 };
2072
2073 /** Equality of allocators instantiated with same types T. */
2075 return true;
2076 }
2077 /** Non-equality of allocators instantiated with same types T. */
2078 inline bool operator!=(const ut::allocator<T, Allocator_base> &other) const {
2079 return !(*this == other);
2080 }
2081
2082 /** Return the maximum number of objects that can be allocated by
2083 this allocator. This number is somewhat lower for PFS-enabled
2084 builds because of extra few bytes needed for PFS.
2085 */
2088 return (s_max - ut::pfs_overhead()) / sizeof(T);
2089 }
2090
2091 /** Allocates chunk of memory that can hold n_elements objects of
2092 type T. Returned pointer is always valid. In case underlying
2093 allocation function was not able to fulfill the allocation request,
2094 this function will throw std::bad_alloc exception. After successful
2095 allocation, returned pointer must be passed back to
2096 ut::allocator<T>::deallocate() when no longer needed.
2097
2098 @param[in] n_elements number of elements
2099 @param[in] hint pointer to a nearby memory location,
2100 not used by this implementation
2101 @return pointer to the allocated memory
2102 */
2104 const_pointer hint [[maybe_unused]] = nullptr) {
2105 if (unlikely(n_elements > max_size())) {
2106 throw std::bad_array_new_length();
2107 }
2108
2109 auto ptr = Allocator_base::allocate_impl(n_elements * sizeof(T));
2110
2111 if (unlikely(!ptr)) {
2112 throw std::bad_alloc();
2113 }
2114
2115 return static_cast<pointer>(ptr);
2116 }
2117
2118 /** Releases the memory allocated through ut::allocator<T>::allocate().
2119
2120 @param[in,out] ptr pointer to memory to free
2121 @param[in] n_elements number of elements allocated (unused)
2122 */
2123 void deallocate(pointer ptr, size_type n_elements [[maybe_unused]] = 0) {
2124 ut::free(ptr);
2125 }
2126};
2127
2128namespace detail {
2129template <typename>
2130constexpr bool is_unbounded_array_v = false;
2131template <typename T>
2132constexpr bool is_unbounded_array_v<T[]> = true;
2133
2134template <typename>
2135constexpr bool is_bounded_array_v = false;
2136template <typename T, std::size_t N>
2137constexpr bool is_bounded_array_v<T[N]> = true;
2138
2139template <typename>
2140constexpr size_t bounded_array_size_v = 0;
2141template <typename T, std::size_t N>
2143
2144template <typename T>
2145struct Deleter {
2146 void operator()(T *ptr) { ut::delete_(ptr); }
2147};
2148
2149template <typename T>
2151 void operator()(T *ptr) { ut::delete_arr(ptr); }
2152};
2153
2154template <typename T>
2156 void operator()(T *ptr) { ut::aligned_delete(ptr); }
2157};
2158
2159template <typename T>
2162};
2163
2164} // namespace detail
2165
2166/** Dynamically allocates storage for an object of type T. Constructs the object
2167 of type T with provided Args. Wraps the pointer to T instance into the
2168 std::unique_ptr.
2169
2170 This overload participates in overload resolution only if T
2171 is not an array type.
2172
2173 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2174 through PFS, observability for particular parts of the system which want to
2175 use it will be lost or in best case inaccurate. Please have a strong reason
2176 to do so.
2177
2178 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2179 @return std::unique_ptr holding a pointer to instance of T.
2180 */
2181template <typename T, typename Deleter = detail::Deleter<T>, typename... Args>
2182std::enable_if_t<!std::is_array<T>::value, std::unique_ptr<T, Deleter>>
2183make_unique(Args &&...args) {
2184 return std::unique_ptr<T, Deleter>(ut::new_<T>(std::forward<Args>(args)...));
2185}
2186
2187/** Dynamically allocates storage for an object of type T. Constructs the object
2188 of type T with provided Args. Wraps the pointer to T instance into the
2189 std::unique_ptr with custom deleter which knows how to handle PFS-enabled
2190 dynamic memory allocations. Instruments the memory with given PSI memory key
2191 in case PFS memory support is enabled.
2192
2193 This overload participates in overload resolution only if T
2194 is not an array type.
2195
2196 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2197 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2198 @return std::unique_ptr holding a pointer to instance of T.
2199 */
2200template <typename T, typename Deleter = detail::Deleter<T>, typename... Args>
2201std::enable_if_t<!std::is_array<T>::value, std::unique_ptr<T, Deleter>>
2203 return std::unique_ptr<T, Deleter>(
2204 ut::new_withkey<T>(key, std::forward<Args>(args)...));
2205}
2206
2207/** Dynamically allocates storage for an object of type T. Constructs the object
2208 of type T with provided Args. Wraps the pointer to an array of T instance
2209 into the std::unique_ptr.
2210
2211 This overload participates in overload resolution only if T
2212 is an array type with unknown compile-time bound.
2213
2214 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2215 through PFS, observability for particular parts of the system which want to
2216 use it will be lost or in best case inaccurate. Please have a strong reason
2217 to do so.
2218
2219 @return std::unique_ptr holding a pointer to an array of size instances of
2220 T.
2221 */
2222template <typename T,
2223 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2224std::enable_if_t<detail::is_unbounded_array_v<T>, std::unique_ptr<T, Deleter>>
2226 return std::unique_ptr<T, Deleter>(
2227 ut::new_arr<std::remove_extent_t<T>>(ut::Count{size}));
2228}
2229
2230/** Dynamically allocates storage for an object of type T. Constructs the object
2231 of type T with provided Args. Wraps the pointer to an array of T instances
2232 into the std::unique_ptr with custom deleter which knows how to handle
2233 PFS-enabled dynamic memory allocations. Instruments the memory with given
2234 PSI memory key in case PFS memory support is enabled.
2235
2236 This overload participates in overload resolution only if T
2237 is an array type with unknown compile-time bound.
2238
2239 @return std::unique_ptr holding a pointer to an array of size instances of
2240 T.
2241 */
2242template <typename T,
2243 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2244std::enable_if_t<detail::is_unbounded_array_v<T>, std::unique_ptr<T, Deleter>>
2246 return std::unique_ptr<T, Deleter>(
2247 ut::new_arr_withkey<std::remove_extent_t<T>>(key, ut::Count{size}));
2248}
2249
2250/** std::unique_ptr for arrays of known compile-time bound are disallowed.
2251
2252 For more details see 4.3 paragraph from
2253 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3588.txt
2254 */
2255template <typename T, typename... Args>
2256std::enable_if_t<detail::is_bounded_array_v<T>> make_unique(Args &&...) =
2257 delete;
2258
2259/** std::unique_ptr in PFS-enabled builds for arrays of known compile-time bound
2260 are disallowed.
2261
2262 For more details see 4.3 paragraph from
2263 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3588.txt
2264 */
2265template <typename T, typename... Args>
2266std::enable_if_t<detail::is_bounded_array_v<T>> make_unique(
2267 PSI_memory_key_t key, Args &&...) = delete;
2268
2269/** The following is a common type that is returned by all the ut::make_unique
2270 (non-aligned) specializations listed above. This is effectively a if-ladder
2271 for the following list of conditions on the input type:
2272 !std::is_array<T>::value -> std::unique_ptr<T, detail::Deleter<T>>
2273 detail::is_unbounded_array_v<T> ->
2274 std::unique_ptr<T,detail::Array_deleter<std::remove_extent_t<T>>> else (or
2275 else if detail::is_bounded_array_v<T>) -> void (we do not support bounded
2276 array ut::make_unique)
2277 */
2278template <typename T>
2279using unique_ptr = std::conditional_t<
2280 !std::is_array<T>::value, std::unique_ptr<T, detail::Deleter<T>>,
2281 std::conditional_t<
2282 detail::is_unbounded_array_v<T>,
2283 std::unique_ptr<T, detail::Array_deleter<std::remove_extent_t<T>>>,
2284 void>>;
2285
2286/** Dynamically allocates storage for an object of type T at address aligned to
2287 the requested alignment. Constructs the object of type T with provided Args.
2288 Wraps the pointer to T instance into the std::unique_ptr.
2289
2290 This overload participates in overload resolution only if T
2291 is not an array type.
2292
2293 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2294 through PFS, observability for particular parts of the system which want to
2295 use it will be lost or in best case inaccurate. Please have a strong reason
2296 to do so.
2297
2298 @param[in] alignment Alignment requirement for storage to be allocated.
2299 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2300 @return std::unique_ptr holding a pointer to instance of T.
2301 */
2302template <typename T, typename Deleter = detail::Aligned_deleter<T>,
2303 typename... Args>
2304std::enable_if_t<!std::is_array<T>::value, std::unique_ptr<T, Deleter>>
2305make_unique_aligned(size_t alignment, Args &&...args) {
2306 return std::unique_ptr<T, Deleter>(
2307 ut::aligned_new<T>(alignment, std::forward<Args>(args)...));
2308}
2309
2310/** Dynamically allocates storage for an array of objects of type T at address
2311 aligned to the requested alignment. Constructs the object of type T with
2312 provided Args. Wraps the pointer to T instance into the std::unique_ptr with
2313 custom deleter which knows how to handle PFS-enabled dynamic memory
2314 allocations. Instruments the memory with given PSI memory key in case PFS
2315 memory support is enabled.
2316
2317 This overload participates in overload resolution only if T is not an array
2318 type.
2319
2320 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2321 @param[in] alignment Alignment requirement for storage to be allocated.
2322 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2323 @return std::unique_ptr holding a pointer to instance of T.
2324 */
2325template <typename T, typename Deleter = detail::Aligned_deleter<T>,
2326 typename... Args>
2327std::enable_if_t<!std::is_array<T>::value, std::unique_ptr<T, Deleter>>
2328make_unique_aligned(PSI_memory_key_t key, size_t alignment, Args &&...args) {
2329 return std::unique_ptr<T, Deleter>(
2330 ut::aligned_new_withkey<T>(key, alignment, std::forward<Args>(args)...));
2331}
2332
2333/** Dynamically allocates storage for an array of type T having specified
2334 number of elements. The storage will start at an address aligned to the
2335 requested alignment and pointer to it will be wrapped in std::unique_ptr
2336 returned.
2337
2338 Elements of the array will be default-constructed.
2339
2340 This overload participates in overload resolution only if T is an array type
2341 with unknown compile-time bound.
2342
2343 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2344 through PFS, observability for particular parts of the system which want to
2345 use it will be lost or in best case inaccurate. Please have a strong reason
2346 to do so.
2347
2348 @param[in] alignment Alignment requirement for storage to be allocated.
2349 @param[in] size Size of the array of objects T to allocate.
2350 @return std::unique_ptr holding a pointer to an array of size instances of
2351 T.
2352 */
2353template <typename T, typename Deleter = detail::Aligned_array_deleter<
2354 std::remove_extent_t<T>>>
2355std::enable_if_t<detail::is_unbounded_array_v<T>, std::unique_ptr<T, Deleter>>
2356make_unique_aligned(size_t alignment, size_t size) {
2357 return std::unique_ptr<T, Deleter>(
2358 ut::aligned_new_arr<std::remove_extent_t<T>>(alignment, ut::Count{size}));
2359}
2360
2361/** Dynamically allocates storage for an array of type T having specified
2362 number of elements. The storage will start at an address aligned to the
2363 requested alignment and pointer to it will be wrapped in std::unique_ptr
2364 with custom deleter which knows how to handle PFS-enabled dynamic memory
2365 allocations. Instruments the memory with given PSI memory key in case PFS
2366 memory support is enabled.
2367
2368 Elements of the array will be default-constructed.
2369
2370 This overload participates in overload resolution only if T is an array type
2371 with unknown compile-time bound.
2372
2373 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2374 @param[in] alignment Alignment requirement for storage to be allocated.
2375 @param[in] size Size of the array of objects T to allocate.
2376 @return std::unique_ptr holding a pointer to an array of size instances of
2377 T.
2378 */
2379template <typename T, typename Deleter = detail::Aligned_array_deleter<
2380 std::remove_extent_t<T>>>
2381std::enable_if_t<detail::is_unbounded_array_v<T>, std::unique_ptr<T, Deleter>>
2382make_unique_aligned(PSI_memory_key_t key, size_t alignment, size_t size) {
2383 return std::unique_ptr<T, Deleter>(
2384 ut::aligned_new_arr_withkey<std::remove_extent_t<T>>(key, alignment,
2385 ut::Count{size}));
2386}
2387
2388/** std::unique_ptr for arrays of known compile-time bound are disallowed.
2389
2390 For more details see 4.3 paragraph from
2391 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3588.txt
2392 */
2393template <typename T, typename... Args>
2394std::enable_if_t<detail::is_bounded_array_v<T>> make_unique_aligned(
2395 Args &&...) = delete;
2396
2397/** std::unique_ptr in PFS-enabled builds for arrays of known compile-time bound
2398 are disallowed.
2399
2400 For more details see 4.3 paragraph from
2401 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3588.txt
2402 */
2403template <typename T, typename... Args>
2404std::enable_if_t<detail::is_bounded_array_v<T>> make_unique_aligned(
2405 PSI_memory_key_t key, Args &&...) = delete;
2406
2407/** The following is a common type that is returned by all the
2408 ut::make_unique_aligned (non-aligned) specializations listed above. This is
2409 effectively a if-ladder for the following list of conditions on the input
2410 type: !std::is_array<T>::value -> std::unique_ptr<T,
2411 detail::Aligned_deleter<T>> detail::is_unbounded_array_v<T> ->
2412 std::unique_ptr<T,detail::Aligned_array_deleter<std::remove_extent_t<T>>>
2413 else (or else if detail::is_bounded_array_v<T>) -> void (we do not support
2414 bounded array ut::make_unique)
2415 */
2416template <typename T>
2417using unique_ptr_aligned = std::conditional_t<
2418 !std::is_array<T>::value, std::unique_ptr<T, detail::Aligned_deleter<T>>,
2419 std::conditional_t<detail::is_unbounded_array_v<T>,
2421 std::remove_extent_t<T>>>,
2422 void>>;
2423
2424/** Dynamically allocates storage for an object of type T. Constructs the object
2425 of type T with provided Args. Wraps the pointer to T instance into the
2426 std::shared_ptr.
2427
2428 This overload participates in overload resolution only if T
2429 is not an array type.
2430
2431 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2432 through PFS, observability for particular parts of the system which want to
2433 use it will be lost or in best case inaccurate. Please have a strong reason
2434 to do so.
2435
2436 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2437 @return std::shared_ptr holding a pointer to instance of T.
2438 */
2439template <typename T, typename Deleter = detail::Deleter<T>, typename... Args>
2441 Args &&...args) {
2442 return std::shared_ptr<T>(ut::new_<T>(std::forward<Args>(args)...),
2443 Deleter{});
2444}
2445
2446/** Dynamically allocates storage for an object of type T. Constructs the object
2447 of type T with provided Args. Wraps the pointer to T instance into the
2448 std::shared_ptr with custom deleter which knows how to handle PFS-enabled
2449 dynamic memory allocations. Instruments the memory with given PSI memory key
2450 in case PFS memory support is enabled.
2451
2452 This overload participates in overload resolution only if T
2453 is not an array type.
2454
2455 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2456 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2457 @return std::shared_ptr holding a pointer to instance of T.
2458 */
2459template <typename T, typename Deleter = detail::Deleter<T>, typename... Args>
2461 PSI_memory_key_t key, Args &&...args) {
2462 return std::shared_ptr<T>(
2463 ut::new_withkey<T>(key, std::forward<Args>(args)...), Deleter{});
2464}
2465
2466/** Dynamically allocates storage for an array of requested size of objects of
2467 type T. Constructs the object of type T with provided Args. Wraps the
2468 pointer to an array of T instance into the std::shared_ptr.
2469
2470 This overload participates in overload resolution only if T
2471 is an array type with unknown compile-time bound.
2472
2473 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2474 through PFS, observability for particular parts of the system which want to
2475 use it will be lost or in best case inaccurate. Please have a strong reason
2476 to do so.
2477
2478 @param[in] size Size of the array of objects T to allocate.
2479 @return std::shared_ptr holding a pointer to an array of size instances of
2480 T.
2481 */
2482template <typename T,
2483 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2484std::enable_if_t<detail::is_unbounded_array_v<T>, std::shared_ptr<T>>
2486 return std::shared_ptr<T>(
2487 ut::new_arr<std::remove_extent_t<T>>(ut::Count{size}), Deleter{});
2488}
2489
2490/** Dynamically allocates storage for an array of requested size of objects of
2491 type T. Constructs the object of type T with provided Args. Wraps the
2492 pointer to an array of T instances into the std::shared_ptr with custom
2493 deleter which knows how to handle PFS-enabled dynamic memory allocations.
2494 Instruments the memory with given PSI memory key in case PFS memory support
2495 is enabled.
2496
2497 This overload participates in overload resolution only if T
2498 is an array type with unknown compile-time bound.
2499
2500 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2501 @param[in] size Size of the array of objects T to allocate.
2502 @return std::shared_ptr holding a pointer to an array of size instances of
2503 T.
2504 */
2505template <typename T,
2506 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2507std::enable_if_t<detail::is_unbounded_array_v<T>, std::shared_ptr<T>>
2509 return std::shared_ptr<T>(
2510 ut::new_arr_withkey<std::remove_extent_t<T>>(key, ut::Count{size}),
2511 Deleter{});
2512}
2513
2514/** Dynamically allocates storage for an array of objects of type T. Constructs
2515 the object of type T with provided Args. Wraps the pointer to an array of T
2516 instance into the std::shared_ptr.
2517
2518 This overload participates in overload resolution only if T
2519 is an array type with known compile-time bound.
2520
2521 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2522 through PFS, observability for particular parts of the system which want to
2523 use it will be lost or in best case inaccurate. Please have a strong reason
2524 to do so.
2525
2526 @return std::shared_ptr holding a pointer to an array of size instances of
2527 T.
2528 */
2529template <typename T,
2530 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2531std::enable_if_t<detail::is_bounded_array_v<T>, std::shared_ptr<T>>
2533 return std::shared_ptr<T>(ut::new_arr<std::remove_extent_t<T>>(
2534 ut::Count{detail::bounded_array_size_v<T>}),
2535 Deleter{});
2536}
2537
2538/** Dynamically allocates storage for an array of objects of type T. Constructs
2539 the object of type T with provided Args. Wraps the pointer to an array of T
2540 instances into the std::shared_ptr with custom deleter which knows how to
2541 handle PFS-enabled dynamic memory allocations. Instruments the memory with
2542 given PSI memory key in case PFS memory support is enabled.
2543
2544 This overload participates in overload resolution only if T
2545 is an array type with known compile-time bound.
2546
2547 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2548 @return std::shared_ptr holding a pointer to an array of size instances of
2549 T.
2550 */
2551template <typename T,
2552 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2553std::enable_if_t<detail::is_bounded_array_v<T>, std::shared_ptr<T>> make_shared(
2555 return std::shared_ptr<T>(
2556 ut::new_arr_withkey<std::remove_extent_t<T>>(
2557 key, ut::Count{detail::bounded_array_size_v<T>}),
2558 Deleter{});
2559}
2560
2561/** Dynamically allocates storage for an object of type T at address aligned to
2562 the requested alignment. Constructs the object of type T with provided Args.
2563 Wraps the pointer to T instance into the std::shared_ptr.
2564
2565 This overload participates in overload resolution only if T
2566 is not an array type.
2567
2568 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2569 through PFS, observability for particular parts of the system which want to
2570 use it will be lost or in best case inaccurate. Please have a strong reason
2571 to do so.
2572
2573 @param[in] alignment Alignment requirement for storage to be allocated.
2574 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2575 @return std::shared_ptr holding a pointer to instance of T.
2576 */
2577template <typename T, typename Deleter = detail::Aligned_deleter<T>,
2578 typename... Args>
2580make_shared_aligned(size_t alignment, Args &&...args) {
2581 return std::shared_ptr<T>(
2582 ut::aligned_new<T>(alignment, std::forward<Args>(args)...), Deleter{});
2583}
2584
2585/** Dynamically allocates storage for an object of type T at address aligned to
2586 the requested alignment. Constructs the object of type T with provided Args.
2587 Wraps the pointer to T instance into the std::shared_ptr with custom deleter
2588 which knows how to handle PFS-enabled dynamic memory allocations.
2589 Instruments the memory with given PSI memory key in case PFS memory support
2590 is enabled.
2591
2592 This overload participates in overload resolution only if T
2593 is not an array type.
2594
2595 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2596 @param[in] alignment Alignment requirement for storage to be allocated.
2597 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2598 @return std::shared_ptr holding a pointer to instance of T.
2599 */
2600template <typename T, typename Deleter = detail::Aligned_deleter<T>,
2601 typename... Args>
2603make_shared_aligned(PSI_memory_key_t key, size_t alignment, Args &&...args) {
2604 return std::shared_ptr<T>(
2605 ut::aligned_new_withkey<T>(key, alignment, std::forward<Args>(args)...),
2606 Deleter{});
2607}
2608
2609/** Dynamically allocates storage for an array of requested size of objects of
2610 type T at address aligned to the requested alignment. Constructs the object
2611 of type T with provided Args. Wraps the pointer to an array of T instance
2612 into the std::shared_ptr.
2613
2614 This overload participates in overload resolution only if T
2615 is an array type with unknown compile-time bound.
2616
2617 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2618 through PFS, observability for particular parts of the system which want to
2619 use it will be lost or in best case inaccurate. Please have a strong reason
2620 to do so.
2621
2622 @param[in] alignment Alignment requirement for storage to be allocated.
2623 @param[in] size Size of the array of objects T to allocate.
2624 @return std::shared_ptr holding a pointer to an array of size instances of
2625 T.
2626 */
2627template <typename T, typename Deleter = detail::Aligned_array_deleter<
2628 std::remove_extent_t<T>>>
2629std::enable_if_t<detail::is_unbounded_array_v<T>, std::shared_ptr<T>>
2630make_shared_aligned(size_t alignment, size_t size) {
2631 return std::shared_ptr<T>(
2632 ut::aligned_new_arr<std::remove_extent_t<T>>(alignment, ut::Count{size}),
2633 Deleter{});
2634}
2635
2636/** Dynamically allocates storage for an array of requested size of objects of
2637 type T at address aligned to the requested alignment. Constructs the object
2638 of type T with provided Args. Wraps the pointer to an array of T instances
2639 into the std::shared_ptr with custom deleter which knows how to handle
2640 PFS-enabled dynamic memory allocations. Instruments the memory with given
2641 PSI memory key in case PFS memory support is enabled.
2642
2643 This overload participates in overload resolution only if T
2644 is an array type with unknown compile-time bound.
2645
2646 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2647 @param[in] alignment Alignment requirement for storage to be allocated.
2648 @param[in] size Size of the array of objects T to allocate.
2649 @return std::shared_ptr holding a pointer to an array of size instances of
2650 T.
2651 */
2652template <typename T, typename Deleter = detail::Aligned_array_deleter<
2653 std::remove_extent_t<T>>>
2654std::enable_if_t<detail::is_unbounded_array_v<T>, std::shared_ptr<T>>
2655make_shared_aligned(PSI_memory_key_t key, size_t alignment, size_t size) {
2656 return std::shared_ptr<T>(
2657 ut::aligned_new_arr_withkey<std::remove_extent_t<T>>(key, alignment,
2658 ut::Count{size}),
2659 Deleter{});
2660}
2661
2662/** Dynamically allocates storage for an array of objects of type T at address
2663 aligned to the requested alignment. Constructs the object of type T with
2664 provided Args. Wraps the pointer to an array of T instance into the
2665 std::shared_ptr.
2666
2667 This overload participates in overload resolution only if T
2668 is an array type with known compile-time bound.
2669
2670 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2671 through PFS, observability for particular parts of the system which want to
2672 use it will be lost or in best case inaccurate. Please have a strong reason
2673 to do so.
2674
2675 @param[in] alignment Alignment requirement for storage to be allocated.
2676 @return std::shared_ptr holding a pointer to an array of size instances of
2677 T.
2678 */
2679template <typename T, typename Deleter = detail::Aligned_array_deleter<
2680 std::remove_extent_t<T>>>
2681std::enable_if_t<detail::is_bounded_array_v<T>, std::shared_ptr<T>>
2682make_shared_aligned(size_t alignment) {
2683 return std::shared_ptr<T>(
2684 ut::aligned_new_arr<std::remove_extent_t<T>>(
2685 alignment, ut::Count{detail::bounded_array_size_v<T>}),
2686 Deleter{});
2687}
2688
2689/** Dynamically allocates storage for an array of objects of type T at address
2690 aligned to the requested alignment. Constructs the object of type T with
2691 provided Args. Wraps the pointer to an array of T instances into the
2692 std::shared_ptr with custom deleter which knows how to handle PFS-enabled
2693 dynamic memory allocations. Instruments the memory with given PSI memory key
2694 in case PFS memory support is enabled.
2695
2696 This overload participates in overload resolution only if T
2697 is an array type with known compile-time bound.
2698
2699 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2700 @param[in] alignment Alignment requirement for storage to be allocated.
2701 @return std::shared_ptr holding a pointer to an array of size instances of
2702 T.
2703 */
2704template <typename T, typename Deleter = detail::Aligned_array_deleter<
2705 std::remove_extent_t<T>>>
2706std::enable_if_t<detail::is_bounded_array_v<T>, std::shared_ptr<T>>
2708 return std::shared_ptr<T>(
2709 ut::aligned_new_arr_withkey<std::remove_extent_t<T>>(
2710 key, alignment, ut::Count{detail::bounded_array_size_v<T>}),
2711 Deleter{});
2712}
2713
2714/** Specialization of basic_ostringstream which uses ut::allocator. Please note
2715 that it's .str() method returns std::basic_string which is not std::string,
2716 so it has similar API (in particular .c_str()), but you can't assign it to
2717 regular, std::string.
2718 */
2720 std::basic_ostringstream<char, std::char_traits<char>, ut::allocator<char>>;
2721
2722/** Specialization of vector which uses allocator. */
2723template <typename T>
2724using vector = std::vector<T, ut::allocator<T>>;
2725
2726/** Specialization of list which uses ut_allocator. */
2727template <typename T>
2728using list = std::list<T, ut::allocator<T>>;
2729
2730/** Specialization of set which uses ut_allocator. */
2731template <typename Key, typename Compare = std::less<Key>>
2732using set = std::set<Key, Compare, ut::allocator<Key>>;
2733
2734template <typename Key>
2736 std::unordered_set<Key, std::hash<Key>, std::equal_to<Key>,
2738
2739/** Specialization of map which uses ut_allocator. */
2740template <typename Key, typename Value, typename Compare = std::less<Key>>
2741using map =
2742 std::map<Key, Value, Compare, ut::allocator<std::pair<const Key, Value>>>;
2743
2744template <typename Key, typename Value, typename Hash = std::hash<Key>,
2745 typename Key_equal = std::equal_to<Key>>
2747 std::unordered_map<Key, Value, Hash, Key_equal,
2749
2750} // namespace ut
2751
2752#endif /* ut0new_h */
Definition: tls_cipher.cc:38
Lightweight convenience wrapper which manages a dynamically allocated array of over-aligned types.
Definition: ut0new.h:1859
void dealloc()
Invokes destructors of instances of type T, if applicable.
Definition: ut0new.h:1947
void alloc(Count count)
Allocates sufficiently large memory of dynamic storage duration to fit the array of size number of el...
Definition: ut0new.h:1881
void alloc(Args &&...args)
Allocates sufficiently large memory of dynamic storage duration to fit the array of size number of el...
Definition: ut0new.h:1899
void alloc_withkey(PSI_memory_key_t key, Args &&...args)
Allocates sufficiently large memory of dynamic storage duration to fit the array of size number of el...
Definition: ut0new.h:1937
T * ptr
Definition: ut0new.h:1860
void alloc_withkey(PSI_memory_key_t key, Count count)
Allocates sufficiently large memory of dynamic storage duration to fit the array of size number of el...
Definition: ut0new.h:1917
~aligned_array_pointer()
Destructor.
Definition: ut0new.h:1867
Lightweight convenience wrapper which manages dynamically allocated over-aligned type.
Definition: ut0new.h:1765
void alloc_withkey(PSI_memory_key_t key, Args &&...args)
Allocates sufficiently large memory of dynamic storage duration to fit the instance of type T at the ...
Definition: ut0new.h:1804
void alloc(Args &&...args)
Allocates sufficiently large memory of dynamic storage duration to fit the instance of type T at the ...
Definition: ut0new.h:1787
~aligned_pointer()
Destructor.
Definition: ut0new.h:1773
T * ptr
Definition: ut0new.h:1766
void dealloc()
Invokes the destructor of instance of type T, if applicable.
Definition: ut0new.h:1813
Allocator that allows std containers to manage their memory through ut::malloc* and ut::free library ...
Definition: ut0new.h:2023
T & reference
Definition: ut0new.h:2027
void deallocate(pointer ptr, size_type n_elements=0)
Releases the memory allocated through ut::allocator<T>::allocate().
Definition: ut0new.h:2123
~allocator()=default
const T * const_pointer
Definition: ut0new.h:2026
ptrdiff_t difference_type
Definition: ut0new.h:2031
allocator< T, Allocator_base > & operator=(const allocator< T, Allocator_base > &)=default
allocator< T, Allocator_base > & operator=(allocator< T, Allocator_base > &&)=default
T value_type
Definition: ut0new.h:2029
allocator(const allocator< U, Allocator_base > &other)
Copy-construct a new instance of allocator with type T by using existing instance of allocator constr...
Definition: ut0new.h:2060
pointer allocate(size_type n_elements, const_pointer hint=nullptr)
Allocates chunk of memory that can hold n_elements objects of type T.
Definition: ut0new.h:2103
allocator(PSI_memory_key key)
Explicit constructor.
Definition: ut0new.h:2044
size_type max_size() const
Return the maximum number of objects that can be allocated by this allocator.
Definition: ut0new.h:2086
const T & const_reference
Definition: ut0new.h:2028
allocator(allocator< T, Allocator_base > &&)=default
allocator()
Default constructor, use mem_key_std.
Definition: ut0new.h:2039
bool operator!=(const ut::allocator< T, Allocator_base > &other) const
Non-equality of allocators instantiated with same types T.
Definition: ut0new.h:2078
allocator(const allocator< T, Allocator_base > &)=default
size_t size_type
Definition: ut0new.h:2030
bool operator==(const ut::allocator< T, Allocator_base > &) const
Equality of allocators instantiated with same types T.
Definition: ut0new.h:2074
T * pointer
Definition: ut0new.h:2025
Implementation bits and pieces of include/ut0new.h.
unsigned int PSI_memory_key
Instrumented memory key.
Definition: psi_memory_bits.h:49
#define T
Definition: jit_executor_value.cc:373
#define realloc(P, A)
Definition: lexyy.cc:916
#define free(A)
Definition: lexyy.cc:915
A macro that gives FILE without the directory name (e.g.
constexpr bool unlikely(bool expr)
Definition: my_compiler.h:58
static int count
Definition: myisam_ftdump.cc:45
Instrumentation helpers for memory allocation.
std::atomic< Type > N
Definition: ut0counter.h:225
Definition: packet_based_table_with_cursor.h:36
Definition: os0file.h:89
std::string_view Key
The key type for the hash structure in HashJoinRowBuffer.
Definition: hash_join_buffer.h:108
Definition: http_server_component.cc:36
ValueType value(const std::optional< ValueType > &v)
Definition: gtid.h:83
ValueType max(X &&first)
Definition: gtid.h:103
noexcept
The return type for any call_and_catch(f, args...) call where f(args...) returns Type.
Definition: call_and_catch.h:76
size_t size(const char *const c)
Definition: base64.h:46
Alignment
Enum class describing alignment-requirements.
Definition: lock_free_type.h:39
constexpr bool is_unbounded_array_v< T[]>
Definition: ut0new.h:2132
typename select_alloc_impl< Pfs_memory_instrumentation_on >::type select_alloc_impl_t
Just a small helper type which saves us some keystrokes.
Definition: aligned_alloc.h:691
constexpr size_t bounded_array_size_v< T[N]>
Definition: ut0new.h:2142
constexpr bool is_bounded_array_v
Definition: ut0new.h:2135
constexpr bool is_unbounded_array_v
Definition: ut0new.h:2130
typename select_large_page_alloc_impl< Pfs_memory_instrumentation_on >::type select_large_page_alloc_impl_t
Just a small helper type which saves us some keystrokes.
Definition: large_page_alloc.h:367
typename select_page_alloc_impl< Pfs_memory_instrumentation_on >::type select_page_alloc_impl_t
Just a small helper type which saves us some keystrokes.
Definition: page_alloc.h:428
typename select_malloc_impl< Pfs_memory_instrumentation_on, Array_specialization >::type select_malloc_impl_t
Just a small helper type which saves us some keystrokes.
Definition: alloc.h:429
constexpr size_t bounded_array_size_v
Definition: ut0new.h:2140
constexpr bool is_bounded_array_v< T[N]>
Definition: ut0new.h:2137
This file contains a set of libraries providing overloads for regular dynamic allocation routines whi...
Definition: aligned_alloc.h:48
void * aligned_zalloc_withkey(PSI_memory_key_t key, std::size_t size, std::size_t alignment) noexcept
Dynamically allocates zero-initialized storage of given size and at the address aligned to the reques...
Definition: ut0new.h:1368
std::unordered_map< Key, Value, Hash, Key_equal, ut::allocator< std::pair< const Key, Value > > > unordered_map
Definition: ut0new.h:2748
size_t pfs_overhead() noexcept
Returns number of bytes that ut::malloc_*, ut::zalloc_*, ut::realloc_* and ut::new_* variants will be...
Definition: ut0new.h:967
T * aligned_new_withkey(PSI_memory_key_t key, std::size_t alignment, Args &&...args)
Dynamically allocates storage for an object of type T at address aligned to the requested alignment.
Definition: ut0new.h:1436
void * zalloc_withkey(PSI_memory_key_t key, std::size_t size) noexcept
Dynamically allocates zero-initialized storage of given size.
Definition: ut0new.h:474
void * malloc_withkey(PSI_memory_key_t key, std::size_t size) noexcept
Dynamically allocates storage of given size.
Definition: ut0new.h:438
void * aligned_zalloc(std::size_t size, std::size_t alignment) noexcept
Dynamically allocates zero-initialized storage of given size and at the address aligned to the reques...
Definition: ut0new.h:1391
void * malloc_large_page(std::size_t size) noexcept
Dynamically allocates memory backed up by large (huge) pages.
Definition: ut0new.h:1113
std::unordered_set< Key, std::hash< Key >, std::equal_to< Key >, ut::allocator< Key > > unordered_set
Definition: ut0new.h:2737
std::basic_ostringstream< char, std::char_traits< char >, ut::allocator< char > > ostringstream
Specialization of basic_ostringstream which uses ut::allocator.
Definition: ut0new.h:2720
allocation_low_level_info page_low_level_info(void *ptr) noexcept
Retrieves the pointer and size of the allocation provided by the OS.
Definition: ut0new.h:1051
std::vector< T, ut::allocator< T > > vector
Specialization of vector which uses allocator.
Definition: ut0new.h:2724
void aligned_delete_arr(T *ptr) noexcept
Releases storage which has been dynamically allocated through any of the aligned_new_arr_*() variants...
Definition: ut0new.h:1737
std::enable_if_t<!std::is_array< T >::value, std::unique_ptr< T, Deleter > > make_unique(Args &&...args)
Dynamically allocates storage for an object of type T.
Definition: ut0new.h:2183
void delete_(T *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::new*() variants.
Definition: ut0new.h:651
std::set< Key, Compare, ut::allocator< Key > > set
Specialization of set which uses ut_allocator.
Definition: ut0new.h:2732
void * malloc_page(std::size_t size) noexcept
Dynamically allocates system page-aligned storage of given size.
Definition: ut0new.h:1017
void * realloc_withkey(PSI_memory_key_t key, void *ptr, std::size_t size) noexcept
Upsizes or downsizes already dynamically allocated storage to the new size.
Definition: ut0new.h:517
void delete_arr(T *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::new_arr*() variants.
Definition: ut0new.h:951
std::enable_if_t<!std::is_array< T >::value, std::unique_ptr< T, Deleter > > make_unique_aligned(size_t alignment, Args &&...args)
Dynamically allocates storage for an object of type T at address aligned to the requested alignment.
Definition: ut0new.h:2305
T * aligned_new_arr_withkey(PSI_memory_key_t key, std::size_t alignment, Args &&...args)
Dynamically allocates storage for an array of T's at address aligned to the requested alignment.
Definition: ut0new.h:1557
allocation_low_level_info large_page_low_level_info(void *ptr) noexcept
Retrieves the pointer and size of the allocation provided by the OS.
Definition: ut0new.h:1149
bool free_page(void *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::malloc_page*() variants.
Definition: ut0new.h:1067
void * malloc_large_page_withkey(PSI_memory_key_t key, std::size_t size) noexcept
Dynamically allocates memory backed up by large (huge) pages.
Definition: ut0new.h:1089
size_t large_page_allocation_size(void *ptr) noexcept
Retrieves the total amount of bytes that are available for application code to use.
Definition: ut0new.h:1135
std::map< Key, Value, Compare, ut::allocator< std::pair< const Key, Value > > > map
Specialization of map which uses ut_allocator.
Definition: ut0new.h:2742
std::enable_if_t<!std::is_array< T >::value, std::shared_ptr< T > > make_shared_aligned(size_t alignment, Args &&...args)
Dynamically allocates storage for an object of type T at address aligned to the requested alignment.
Definition: ut0new.h:2580
void * malloc(std::size_t size) noexcept
Dynamically allocates storage of given size.
Definition: ut0new.h:459
std::conditional_t< !std::is_array< T >::value, std::unique_ptr< T, detail::Deleter< T > >, std::conditional_t< detail::is_unbounded_array_v< T >, std::unique_ptr< T, detail::Array_deleter< std::remove_extent_t< T > > >, void > > unique_ptr
The following is a common type that is returned by all the ut::make_unique (non-aligned) specializati...
Definition: ut0new.h:2284
T * aligned_new_arr(std::size_t alignment, Args &&...args)
Dynamically allocates storage for an array of T's at address aligned to the requested alignment.
Definition: ut0new.h:1680
T * new_(Args &&...args)
Dynamically allocates storage for an object of type T.
Definition: ut0new.h:636
std::list< T, ut::allocator< T > > list
Specialization of list which uses ut_allocator.
Definition: ut0new.h:2728
void free(void *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::malloc*(),...
Definition: ut0new.h:559
PSI_memory_key_t make_psi_memory_key(PSI_memory_key key)
Convenience helper function to create type-safe representation of PSI_memory_key.
Definition: ut0new.h:190
void * aligned_alloc_withkey(PSI_memory_key_t key, std::size_t size, std::size_t alignment) noexcept
Dynamically allocates storage of given size and at the address aligned to the requested alignment.
Definition: ut0new.h:1326
constexpr bool WITH_PFS_MEMORY
Definition: ut0new.h:422
void aligned_delete(T *ptr) noexcept
Releases storage which has been dynamically allocated through any of the aligned_new_*() variants.
Definition: ut0new.h:1492
void * malloc_page_withkey(PSI_memory_key_t key, std::size_t size) noexcept
Dynamically allocates system page-aligned storage of given size.
Definition: ut0new.h:990
std::conditional_t< !std::is_array< T >::value, std::unique_ptr< T, detail::Aligned_deleter< T > >, std::conditional_t< detail::is_unbounded_array_v< T >, std::unique_ptr< T, detail::Aligned_array_deleter< std::remove_extent_t< T > > >, void > > unique_ptr_aligned
The following is a common type that is returned by all the ut::make_unique_aligned (non-aligned) spec...
Definition: ut0new.h:2422
void * realloc(void *ptr, std::size_t size) noexcept
Upsizes or downsizes already dynamically allocated storage to the new size.
Definition: ut0new.h:545
T * new_arr_withkey(PSI_memory_key_t key, Args &&...args)
Dynamically allocates storage for an array of T's.
Definition: ut0new.h:716
T * new_withkey(PSI_memory_key_t key, Args &&...args)
Dynamically allocates storage for an object of type T.
Definition: ut0new.h:593
size_t page_allocation_size(void *ptr) noexcept
Retrieves the total amount of bytes that are available for application code to use.
Definition: ut0new.h:1037
bool free_large_page(void *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::malloc_large_page*() var...
Definition: ut0new.h:1166
std::enable_if_t<!std::is_array< T >::value, std::shared_ptr< T > > make_shared(Args &&...args)
Dynamically allocates storage for an object of type T.
Definition: ut0new.h:2440
void aligned_free(void *ptr) noexcept
Releases storage which has been dynamically allocated through any of the aligned_alloc_*() or aligned...
Definition: ut0new.h:1405
void * aligned_alloc(std::size_t size, std::size_t alignment) noexcept
Dynamically allocates storage of given size and at the address aligned to the requested alignment.
Definition: ut0new.h:1349
T * new_arr(Args &&...args)
Dynamically allocates storage for an array of T's.
Definition: ut0new.h:801
T * aligned_new(std::size_t alignment, Args &&...args)
Dynamically allocates storage for an object of type T at address aligned to the requested alignment.
Definition: ut0new.h:1477
void * zalloc(std::size_t size) noexcept
Dynamically allocates zero-initialized storage of given size.
Definition: ut0new.h:495
The interface to the operating system process control primitives.
bool os_use_large_pages
Whether to use large pages in the buffer pool.
Definition: os0proc.cc:51
The interface to the operating system process and thread control primitives.
Performance schema instrumentation interface.
Performance schema instrumentation interface.
required string key
Definition: replication_asynchronous_connection_failover.proto:60
static MEM_ROOT mem
Definition: sql_servers.cc:100
Memory instrument information.
Definition: psi_memory_bits.h:58
Definition: ut0new.h:401
static constexpr int value
Definition: ut0new.h:402
Light-weight and type-safe wrapper which serves a purpose of being able to select proper ut::new_arr*...
Definition: ut0new.h:823
Count(size_t count)
Definition: ut0new.h:824
size_t m_count
Definition: ut0new.h:826
size_t operator()() const
Definition: ut0new.h:825
Light-weight and type-safe wrapper around the PSI_memory_key that eliminates the possibility of intro...
Definition: ut0new.h:178
PSI_memory_key operator()() const
Definition: ut0new.h:180
PSI_memory_key m_key
Definition: ut0new.h:181
PSI_memory_key_t(PSI_memory_key key)
Definition: ut0new.h:179
Can be used to extract pointer and size of the allocation provided by the OS.
Definition: ut0new.h:140
void * base_ptr
A pointer returned by the OS allocator.
Definition: ut0new.h:142
size_t allocation_size
The size of allocation that OS performed.
Definition: ut0new.h:144
Definition: ut0new.h:2069
Small wrapper which utilizes SFINAE to dispatch the call to appropriate aligned allocator implementat...
Definition: aligned_alloc.h:697
Definition: ut0new.h:2160
void operator()(T *ptr)
Definition: ut0new.h:2161
Definition: ut0new.h:2155
void operator()(T *ptr)
Definition: ut0new.h:2156
Small wrapper which utilizes SFINAE to dispatch the call to appropriate allocator implementation.
Definition: alloc.h:435
Definition: ut0new.h:2150
void operator()(T *ptr)
Definition: ut0new.h:2151
Definition: ut0new.h:2145
void operator()(T *ptr)
Definition: ut0new.h:2146
Small wrapper which utilizes SFINAE to dispatch the call to appropriate aligned allocator implementat...
Definition: large_page_alloc.h:373
Small wrapper which utilizes SFINAE to dispatch the call to appropriate aligned allocator implementat...
Definition: page_alloc.h:434
Definition: ut0new.h:1973
void * allocate_impl(size_t n_bytes)
Definition: ut0new.h:1982
const PSI_memory_key m_key
Definition: ut0new.h:1987
PSI_memory_key get_mem_key() const
Definition: ut0new.h:1980
allocator_base_pfs(PSI_memory_key key)
Definition: ut0new.h:1974
allocator_base_pfs(const allocator_base_pfs< U > &other)
Definition: ut0new.h:1977
Definition: ut0new.h:1963
allocator_base(const allocator_base< U > &)
Definition: ut0new.h:1967
void * allocate_impl(size_t n_bytes)
Definition: ut0new.h:1969
allocator_base(PSI_memory_key)
Definition: ut0new.h:1964
Definition: ut0new.h:1173
Version control for database, common definitions, and include files.
#define UT_ARR_SIZE(a)
Definition: univ.i:527
Utilities for byte operations.
Utilities related to CPU cache.
Debug utilities for Innobase.
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:109
#define ut_a(EXPR)
Abort execution if EXPR does not evaluate to nonzero.
Definition: ut0dbg.h:97
PSI_memory_key mem_key_ddl
Definition: ut0new.cc:62
void ut_new_boot_safe()
Setup the internal objects needed for ut::*_withkey() to operate.
Definition: ut0new.cc:140
PSI_memory_key mem_key_mtr_t
Definition: ut0new.cc:57
PSI_memory_key mem_key_redo_log_archive_queue_element
PSI_memory_key mem_key_dict_stats_index_map_t
Definition: ut0new.cc:54
PSI_memory_key mem_key_buf_stat_per_index_t
Definition: ut0new.cc:50
PSI_memory_key mem_key_other
Definition: ut0new.cc:59
PSI_memory_info pfs_info_auto[n_auto]
PSI_memory_key auto_event_keys[n_auto]
constexpr int ut_new_get_key_by_base_file(const char *file, size_t len)
Retrieve a memory key (registered with PFS), given the file name of the caller.
Definition: ut0new.h:377
PSI_memory_key mem_key_fil_space_t
Definition: ut0new.cc:56
constexpr bool ut_string_begins_with(const char *a, const char *b, size_t b_len)
Compute whether a string begins with a given prefix, compile-time.
Definition: ut0new.h:351
PSI_memory_key mem_key_lock_sys
Definition: ut0new.cc:58
constexpr int ut_new_get_key_by_file(const char *file)
Retrieve a memory key (registered with PFS), given the file name of the caller.
Definition: ut0new.h:393
PSI_memory_key mem_key_ahi
Keys for registering allocations with performance schema.
Definition: ut0new.cc:47
void ut_new_boot()
Setup the internal objects needed for ut::*_withkey() to operate.
Definition: ut0new.cc:121
PSI_memory_key mem_key_partitioning
Definition: ut0new.cc:60
PSI_memory_key mem_key_archive
Definition: ut0new.cc:48
static constexpr const char * auto_event_names[]
List of filenames that allocate memory and are instrumented via PFS.
Definition: ut0new.h:248
PSI_memory_key mem_key_std
Definition: ut0new.cc:63
const size_t alloc_max_retries
Maximum number of retries to allocate memory.
Definition: ut0new.cc:43
PSI_memory_key mem_key_row_log_buf
Definition: ut0new.cc:61
PSI_memory_key mem_key_trx_sys_t_rw_trx_ids
Definition: ut0new.cc:64
static constexpr size_t n_auto
Definition: ut0new.h:342
PSI_memory_key mem_key_buf_buf_pool
Definition: ut0new.cc:49
constexpr size_t ut_len_without_extension(const char *file)
Find the length of the filename without its file extension.
Definition: ut0new.h:364
PSI_memory_key mem_key_undo_spaces
Definition: ut0new.cc:65
PSI_memory_key mem_key_ut_lock_free_hash_t
Definition: ut0new.cc:66
PSI_memory_key mem_key_clone
Memory key for clone.
Definition: ut0new.cc:52
PSI_memory_key mem_key_dict_stats_n_diff_on_level
Definition: ut0new.cc:55
PSI_memory_key mem_key_dict_stats_bg_recalc_pool_t
Definition: ut0new.cc:53
Various utilities.
#define PSI_NOT_INSTRUMENTED
Definition: validate_password_imp.cc:44