MySQL 8.0.44
Source Code Documentation
ut0new.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 2014, 2025, 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 */
231/* Please obey alphabetical order in the definitions above. */
232
233/** Setup the internal objects needed for ut::*_withkey() to operate.
234This must be called before the first call to ut::*_withkey(). */
235void ut_new_boot();
236
237/** Setup the internal objects needed for ut::*_withkey() to operate.
238This must be called before the first call to ut::*_withkey(). This
239version of function might be called several times and it will
240simply skip all calls except the first one, during which the
241initialization will happen. */
242void ut_new_boot_safe();
243
244#ifdef UNIV_PFS_MEMORY
245
246/** List of filenames that allocate memory and are instrumented via PFS. */
247static constexpr const char *auto_event_names[] = {
248 /* Keep this list alphabetically sorted. */
249 "api0api",
250 "api0misc",
251 "btr0btr",
252 "btr0cur",
253 "btr0load",
254 "btr0pcur",
255 "btr0sea",
256 "btr0types",
257 "buf",
258 "buf0buddy",
259 "buf0buf",
260 "buf0checksum",
261 "buf0dblwr",
262 "buf0dump",
263 "buf0flu",
264 "buf0lru",
265 "buf0rea",
266 "buf0stats",
267 "buf0types",
268 "checksum",
269 "crc32",
270 "create",
271 "data0data",
272 "data0type",
273 "data0types",
274 "db0err",
275 "ddl0buffer",
276 "ddl0builder",
277 "ddl0ctx",
278 "ddl0ddl",
279 "ddl0file-reader",
280 "ddl0loader",
281 "ddl0merge",
282 "ddl0rtree",
283 "ddl0par-scan",
284 "dict",
285 "dict0boot",
286 "dict0crea",
287 "dict0dd",
288 "dict0dict",
289 "dict0load",
290 "dict0mem",
291 "dict0priv",
292 "dict0sdi",
293 "dict0stats",
294 "dict0stats_bg",
295 "dict0types",
296 "dyn0buf",
297 "dyn0types",
298 "eval0eval",
299 "eval0proc",
300 "fil0fil",
301 "fil0types",
302 "file",
303 "fsp0file",
304 "fsp0fsp",
305 "fsp0space",
306 "fsp0sysspace",
307 "fsp0types",
308 "fts0ast",
309 "fts0blex",
310 "fts0config",
311 "fts0fts",
312 "fts0opt",
313 "fts0pars",
314 "fts0plugin",
315 "fts0priv",
316 "fts0que",
317 "fts0sql",
318 "fts0tlex",
319 "fts0tokenize",
320 "fts0types",
321 "fts0vlc",
322 "fut0fut",
323 "fut0lst",
324 "gis0geo",
325 "gis0rtree",
326 "gis0sea",
327 "gis0type",
328 "ha0ha",
329 "ha0storage",
330 "ha_innodb",
331 "ha_innopart",
332 "ha_prototypes",
333 "handler0alter",
334 "hash0hash",
335 "i_s",
336 "ib0mutex",
337 "ibuf0ibuf",
338 "ibuf0types",
339 "lexyy",
340 "lob0lob",
341 "lock0iter",
342 "lock0lock",
343 "lock0prdt",
344 "lock0priv",
345 "lock0types",
346 "lock0wait",
347 "log0log",
348 "log0recv",
349 "log0write",
350 "mach0data",
351 "mem",
352 "mem0mem",
353 "memory",
354 "mtr0log",
355 "mtr0mtr",
356 "mtr0types",
357 "os0atomic",
358 "os0event",
359 "os0file",
360 "os0numa",
361 "os0once",
362 "os0proc",
363 "os0thread",
364 "page",
365 "page0cur",
366 "page0page",
367 "page0size",
368 "page0types",
369 "page0zip",
370 "pars0grm",
371 "pars0lex",
372 "pars0opt",
373 "pars0pars",
374 "pars0sym",
375 "pars0types",
376 "que0que",
377 "que0types",
378 "read0read",
379 "read0types",
380 "rec",
381 "rem0cmp",
382 "rem0rec",
383 "rem0types",
384 "row0ext",
385 "row0ft",
386 "row0import",
387 "row0ins",
388 "row0log",
389 "row0mysql",
390 "row0purge",
391 "row0quiesce",
392 "row0row",
393 "row0sel",
394 "row0types",
395 "row0uins",
396 "row0umod",
397 "row0undo",
398 "row0upd",
399 "row0vers",
400 "sess0sess",
401 "srv0conc",
402 "srv0mon",
403 "srv0srv",
404 "srv0start",
405 "srv0tmp",
406 "sync0arr",
407 "sync0debug",
408 "sync0policy",
409 "sync0sharded_rw",
410 "sync0rw",
411 "sync0sync",
412 "sync0types",
413 "trx0i_s",
414 "trx0purge",
415 "trx0rec",
416 "trx0roll",
417 "trx0rseg",
418 "trx0sys",
419 "trx0trx",
420 "trx0types",
421 "trx0undo",
422 "trx0xa",
423 "usr0sess",
424 "usr0types",
425 "ut",
426 "ut0byte",
427 "ut0counter",
428 "ut0crc32",
429 "ut0dbg",
430 "ut0link_buf",
431 "ut0list",
432 "ut0lock_free_hash",
433 "ut0lst",
434 "ut0mem",
435 "ut0mutex",
436 "ut0new",
437 "ut0pool",
438 "ut0rbt",
439 "ut0rnd",
440 "ut0sort",
441 "ut0stage",
442 "ut0ut",
443 "ut0vec",
444 "ut0wqueue",
445 "zipdecompress",
446};
447
448static constexpr size_t n_auto = UT_ARR_SIZE(auto_event_names);
451
452/** gcc 5 fails to evaluate costexprs at compile time. */
453#if defined(__GNUG__) && (__GNUG__ == 5)
454
455/** Compute whether a string begins with a given prefix, compile-time.
456@param[in] a first string, taken to be zero-terminated
457@param[in] b second string (prefix to search for)
458@param[in] b_len length in bytes of second string
459@param[in] index character index to start comparing at
460@return whether b is a prefix of a */
461constexpr bool ut_string_begins_with(const char *a, const char *b, size_t b_len,
462 size_t index = 0) {
463 return (index == b_len || (a[index] == b[index] &&
464 ut_string_begins_with(a, b, b_len, index + 1)));
465}
466
467/** Find the length of the filename without its file extension.
468@param[in] file filename, with extension but without directory
469@param[in] index character index to start scanning for extension
470 separator at
471@return length, in bytes */
472constexpr size_t ut_len_without_extension(const char *file, size_t index = 0) {
473 return ((file[index] == '\0' || file[index] == '.')
474 ? index
475 : ut_len_without_extension(file, index + 1));
476}
477
478/** Retrieve a memory key (registered with PFS), given the file name of the
479caller.
480@param[in] file portion of the filename - basename, with extension
481@param[in] len length of the filename to check for
482@param[in] index index of first PSI key to check
483@return registered memory key or PSI_NOT_INSTRUMENTED if not found */
485 size_t len,
486 size_t index = 0) {
487 return ((index == n_auto)
490 ? auto_event_keys[index]
491 : ut_new_get_key_by_base_file(file, len, index + 1)));
492}
493
494/** Retrieve a memory key (registered with PFS), given the file name of
495the caller.
496@param[in] file portion of the filename - basename, with extension
497@return registered memory key or PSI_NOT_INSTRUMENTED if not found */
498constexpr PSI_memory_key ut_new_get_key_by_file(const char *file) {
500}
501
502#define UT_NEW_THIS_FILE_PSI_KEY ut_new_get_key_by_file(MY_BASENAME)
503
504#else /* __GNUG__ == 5 */
505
506/** Compute whether a string begins with a given prefix, compile-time.
507@param[in] a first string, taken to be zero-terminated
508@param[in] b second string (prefix to search for)
509@param[in] b_len length in bytes of second string
510@return whether b is a prefix of a */
511constexpr bool ut_string_begins_with(const char *a, const char *b,
512 size_t b_len) {
513 for (size_t i = 0; i < b_len; ++i) {
514 if (a[i] != b[i]) {
515 return false;
516 }
517 }
518 return true;
519}
520
521/** Find the length of the filename without its file extension.
522@param[in] file filename, with extension but without directory
523@return length, in bytes */
524constexpr size_t ut_len_without_extension(const char *file) {
525 for (size_t i = 0;; ++i) {
526 if (file[i] == '\0' || file[i] == '.') {
527 return i;
528 }
529 }
530}
531
532/** Retrieve a memory key (registered with PFS), given the file name of the
533caller.
534@param[in] file portion of the filename - basename, with extension
535@param[in] len length of the filename to check for
536@return index to registered memory key or -1 if not found */
537constexpr int ut_new_get_key_by_base_file(const char *file, size_t len) {
538 for (size_t i = 0; i < n_auto; ++i) {
540 return static_cast<int>(i);
541 }
542 }
543 return -1;
544}
545
546/** Retrieve a memory key (registered with PFS), given the file name of
547the caller.
548@param[in] file portion of the filename - basename, with extension
549@return index to memory key or -1 if not found */
550constexpr int ut_new_get_key_by_file(const char *file) {
552}
553
554// Sending an expression through a template variable forces the compiler to
555// evaluate the expression at compile time (constexpr in itself has no such
556// guarantee, only that the compiler is allowed).
557template <int Value>
559 static constexpr int value = Value;
560};
561
562#define UT_NEW_THIS_FILE_PSI_INDEX \
563 (force_constexpr<ut_new_get_key_by_file(MY_BASENAME)>::value)
564
565#define UT_NEW_THIS_FILE_PSI_KEY \
566 (UT_NEW_THIS_FILE_PSI_INDEX == -1 \
567 ? ut::make_psi_memory_key(PSI_NOT_INSTRUMENTED) \
568 : ut::make_psi_memory_key(auto_event_keys[UT_NEW_THIS_FILE_PSI_INDEX]))
569
570#endif /* __GNUG__ == 5 */
571
572#else
573
574#define UT_NEW_THIS_FILE_PSI_KEY ut::make_psi_memory_key(PSI_NOT_INSTRUMENTED)
575
576#endif /* UNIV_PFS_MEMORY */
577
578namespace ut {
579
580#ifdef HAVE_PSI_MEMORY_INTERFACE
581constexpr bool WITH_PFS_MEMORY = true;
582#else
583constexpr bool WITH_PFS_MEMORY = false;
584#endif
585
586/** Dynamically allocates storage of given size. Instruments the memory with
587 given PSI memory key in case PFS memory support is enabled.
588
589 @param[in] key PSI memory key to be used for PFS memory instrumentation.
590 @param[in] size Size of storage (in bytes) requested to be allocated.
591 @return Pointer to the allocated storage. nullptr if dynamic storage
592 allocation failed.
593
594 Example:
595 int *x = static_cast<int*>(ut::malloc_withkey(key, 10*sizeof(int)));
596 */
597inline void *malloc_withkey(PSI_memory_key_t key, std::size_t size) noexcept {
599 using malloc_impl = detail::Alloc_<impl>;
600 return malloc_impl::alloc<false>(size, key());
601}
602
603/** Dynamically allocates storage of given size.
604
605 NOTE: Given that this function will _NOT_ be instrumenting the allocation
606 through PFS, observability for particular parts of the system which want to
607 use it will be lost or in best case inaccurate. Please have a strong reason
608 to do so.
609
610 @param[in] size Size of storage (in bytes) requested to be allocated.
611 @return Pointer to the allocated storage. nullptr if dynamic storage
612 allocation failed.
613
614 Example:
615 int *x = static_cast<int*>(ut::malloc_withkey(UT_NEW_THIS_FILE_PSI_KEY,
616 10*sizeof(int)));
617 */
618inline void *malloc(std::size_t size) noexcept {
620}
621
622/** Dynamically allocates zero-initialized storage of given size. Instruments
623 the memory with given PSI memory key in case PFS memory support is enabled.
624
625 @param[in] key PSI memory key to be used for PFS memory instrumentation.
626 @param[in] size Size of storage (in bytes) requested to be allocated.
627 @return Pointer to the zero-initialized allocated storage. nullptr if
628 dynamic storage allocation failed.
629
630 Example:
631 int *x = static_cast<int*>(ut::zalloc_withkey(key, 10*sizeof(int)));
632 */
633inline void *zalloc_withkey(PSI_memory_key_t key, std::size_t size) noexcept {
635 using malloc_impl = detail::Alloc_<impl>;
636 return malloc_impl::alloc<true>(size, key());
637}
638
639/** Dynamically allocates zero-initialized storage of given size.
640
641 NOTE: Given that this function will _NOT_ be instrumenting the allocation
642 through PFS, observability for particular parts of the system which want to
643 use it will be lost or in best case inaccurate. Please have a strong reason
644 to do so.
645
646 @param[in] size Size of storage (in bytes) requested to be allocated.
647 @return Pointer to the zero-initialized allocated storage. nullptr if
648 dynamic storage allocation failed.
649
650 Example:
651 int *x = static_cast<int*>(ut::zalloc_withkey(UT_NEW_THIS_FILE_PSI_KEY,
652 10*sizeof(int)));
653 */
654inline void *zalloc(std::size_t size) noexcept {
656}
657
658/** Upsizes or downsizes already dynamically allocated storage to the new size.
659 Instruments the memory with given PSI memory key in case PFS memory support
660 is enabled.
661
662 It also supports standard realloc() semantics by:
663 * allocating size bytes of memory when passed ptr is nullptr
664 * freeing the memory pointed by ptr if passed size is 0
665
666 @param[in] key PSI memory key to be used for PFS memory instrumentation.
667 @param[in] ptr Pointer to the memory area to be reallocated.
668 @param[in] size New size of storage (in bytes) requested to be reallocated.
669 @return Pointer to the reallocated storage. nullptr if dynamic storage
670 allocation failed.
671
672 Example:
673 int *x = static_cast<int*>(ut::malloc_withkey(key, 10*sizeof(int));
674 x = static_cast<int*>(ut::realloc_withkey(key, ptr, 100*sizeof(int)));
675 */
676inline void *realloc_withkey(PSI_memory_key_t key, void *ptr,
677 std::size_t size) noexcept {
679 using malloc_impl = detail::Alloc_<impl>;
680 return malloc_impl::realloc(ptr, size, key());
681}
682
683/** Upsizes or downsizes already dynamically allocated storage to the new size.
684
685 It also supports standard realloc() semantics by:
686 * allocating size bytes of memory when passed ptr is nullptr
687 * freeing the memory pointed by ptr if passed size is 0
688
689 NOTE: Given that this function will _NOT_ be instrumenting the allocation
690 through PFS, observability for particular parts of the system which want to
691 use it will be lost or in best case inaccurate. Please have a strong reason
692 to do so.
693
694 @param[in] ptr Pointer to the memory area to be reallocated.
695 @param[in] size New size of storage (in bytes) requested to be reallocated.
696 @return Pointer to the reallocated storage. nullptr if dynamic storage
697 allocation failed.
698
699 Example:
700 int *x = static_cast<int*>(ut::malloc_withkey(UT_NEW_THIS_FILE_PSI_KEY,
701 10*sizeof(int)); x = static_cast<int*>(ut::realloc(key, ptr,
702 100*sizeof(int)));
703 */
704inline void *realloc(void *ptr, std::size_t size) noexcept {
706 size);
707}
708
709/** Releases storage which has been dynamically allocated through any of
710 the ut::malloc*(), ut::realloc* or ut::zalloc*() variants.
711
712 @param[in] ptr Pointer which has been obtained through any of the
713 ut::malloc*(), ut::realloc* or ut::zalloc*() variants.
714
715 Example:
716 ut::free(ptr);
717 */
718inline void free(void *ptr) noexcept {
720 using malloc_impl = detail::Alloc_<impl>;
722}
723
724/** Dynamically allocates storage for an object of type T. Constructs the object
725 of type T with provided Args. Instruments the memory with given PSI memory
726 key in case PFS memory support is enabled.
727
728 @param[in] key PSI memory key to be used for PFS memory instrumentation.
729 @param[in] args Arguments one wishes to pass over to T constructor(s)
730 @return Pointer to the allocated storage. Throws std::bad_alloc exception
731 if dynamic storage allocation could not be fulfilled. Re-throws whatever
732 exception that may have occurred during the construction of T, in which case
733 it automatically cleans up the raw memory allocated for it.
734
735 Example 1:
736 int *ptr = ut::new_withkey<int>(key);
737
738 Example 2:
739 int *ptr = ut::new_withkey<int>(key, 10);
740 assert(*ptr == 10);
741
742 Example 3:
743 struct A {
744 A(int x, int y) : _x(x), _y(y) {}
745 int _x, _y;
746 };
747 A *ptr = ut::new_withkey<A>(key, 1, 2);
748 assert(ptr->_x == 1);
749 assert(ptr->_y == 2);
750 */
751template <typename T, typename... Args>
752inline T *new_withkey(PSI_memory_key_t key, Args &&...args) {
753 auto mem = ut::malloc_withkey(key, sizeof(T));
754 if (unlikely(!mem)) throw std::bad_alloc();
755 try {
756 new (mem) T(std::forward<Args>(args)...);
757 } catch (...) {
758 ut::free(mem);
759 throw;
760 }
761 return static_cast<T *>(mem);
762}
763
764/** Dynamically allocates storage for an object of type T. Constructs the object
765 of type T with provided Args.
766
767 NOTE: Given that this function will _NOT_ be instrumenting the allocation
768 through PFS, observability for particular parts of the system which want to
769 use it will be lost or in best case inaccurate. Please have a strong reason
770 to do so.
771
772 @param[in] args Arguments one wishes to pass over to T constructor(s)
773 @return Pointer to the allocated storage. Throws std::bad_alloc exception
774 if dynamic storage allocation could not be fulfilled. Re-throws whatever
775 exception that may have occurred during the construction of T, in which case
776 it automatically cleans up the raw memory allocated for it.
777
778 Example 1:
779 int *ptr = ut::new_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY);
780
781 Example 2:
782 int *ptr = ut::new_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY, 10);
783 assert(*ptr == 10);
784
785 Example 3:
786 struct A {
787 A(int x, int y) : _x(x), _y(y) {}
788 int _x, _y;
789 };
790 A *ptr = ut::new_withkey<A>(UT_NEW_THIS_FILE_PSI_KEY, 1, 2);
791 assert(ptr->_x == 1);
792 assert(ptr->_y == 2);
793 */
794template <typename T, typename... Args>
795inline T *new_(Args &&...args) {
796 return ut::new_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
797 std::forward<Args>(args)...);
798}
799
800/** Releases storage which has been dynamically allocated through any of
801 the ut::new*() variants. Destructs the object of type T.
802
803 @param[in] ptr Pointer which has been obtained through any of the
804 ut::new*() variants
805
806 Example:
807 ut::delete_(ptr);
808 */
809template <typename T>
810inline void delete_(T *ptr) noexcept {
811 if (unlikely(!ptr)) return;
812 ptr->~T();
813 ut::free(ptr);
814}
815
816/** Dynamically allocates storage for an array of T's. Constructs objects of
817 type T with provided Args. Arguments that are to be used to construct some
818 respective instance of T shall be wrapped into a std::tuple. See examples
819 down below. Instruments the memory with given PSI memory key in case PFS
820 memory support is enabled.
821
822 To create an array of default-intialized T's, one can use this function
823 template but for convenience purposes one can achieve the same by using
824 the ut::new_arr_withkey with ut::Count overload.
825
826 @param[in] key PSI memory key to be used for PFS memory instrumentation.
827 @param[in] args Tuples of arguments one wishes to pass over to T
828 constructor(s).
829 @return Pointer to the first element of allocated storage. Throws
830 std::bad_alloc exception if dynamic storage allocation could not be
831 fulfilled. Re-throws whatever exception that may have occurred during the
832 construction of any instance of T, in which case it automatically destroys
833 successfully constructed objects till that moment (if any), and finally
834 cleans up the raw memory allocated for T instances.
835
836 Example 1:
837 int *ptr = ut::new_arr_withkey<int>(key,
838 std::forward_as_tuple(1),
839 std::forward_as_tuple(2));
840 assert(ptr[0] == 1);
841 assert(ptr[1] == 2);
842
843 Example 2:
844 struct A {
845 A(int x, int y) : _x(x), _y(y) {}
846 int _x, _y;
847 };
848 A *ptr = ut::new_arr_withkey<A>(key,
849 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
850 std::forward_as_tuple(4, 5), std::forward_as_tuple(6, 7),
851 std::forward_as_tuple(8, 9));
852 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
853 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
854 assert(ptr[2]->_x == 4 && ptr[2]->_y == 5);
855 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
856 assert(ptr[4]->_x == 8 && ptr[4]->_y == 9);
857
858 Example 3:
859 struct A {
860 A() : _x(10), _y(100) {}
861 A(int x, int y) : _x(x), _y(y) {}
862 int _x, _y;
863 };
864 A *ptr = ut::new_arr_withkey<A>(key,
865 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
866 std::forward_as_tuple(), std::forward_as_tuple(6, 7),
867 std::forward_as_tuple());
868 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
869 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
870 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
871 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
872 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
873 */
874template <typename T, typename... Args>
875inline T *new_arr_withkey(PSI_memory_key_t key, Args &&...args) {
877 using malloc_impl = detail::Alloc_<impl>;
878 auto mem = malloc_impl::alloc<false>(sizeof(T) * sizeof...(args), key());
879 if (unlikely(!mem)) throw std::bad_alloc();
880
881 size_t idx = 0;
882 try {
883 (...,
884 detail::construct<T>(mem, sizeof(T) * idx++, std::forward<Args>(args)));
885 } catch (...) {
886 for (size_t offset = (idx - 1) * sizeof(T); offset != 0;
887 offset -= sizeof(T)) {
888 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(mem) + offset -
889 sizeof(T))
890 ->~T();
891 }
893 throw;
894 }
895 return static_cast<T *>(mem);
896}
897
898/** Dynamically allocates storage for an array of T's. Constructs objects of
899 type T with provided Args. Arguments that are to be used to construct some
900 respective instance of T shall be wrapped into a std::tuple. See examples
901 down below.
902
903 To create an array of default-intialized T's, one can use this function
904 template but for convenience purposes one can achieve the same by using
905 the ut::new_arr_withkey with ut::Count overload.
906
907 NOTE: Given that this function will _NOT_ be instrumenting the allocation
908 through PFS, observability for particular parts of the system which want to
909 use it will be lost or in best case inaccurate. Please have a strong reason
910 to do so.
911
912 @param[in] args Tuples of arguments one wishes to pass over to T
913 constructor(s).
914 @return Pointer to the first element of allocated storage. Throws
915 std::bad_alloc exception if dynamic storage allocation could not be
916 fulfilled. Re-throws whatever exception that may have occurred during the
917 construction of any instance of T, in which case it automatically destroys
918 successfully constructed objects till that moment (if any), and finally
919 cleans up the raw memory allocated for T instances.
920
921 Example 1:
922 int *ptr = ut::new_arr_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY,
923 std::forward_as_tuple(1),
924 std::forward_as_tuple(2));
925 assert(ptr[0] == 1);
926 assert(ptr[1] == 2);
927
928 Example 2:
929 struct A {
930 A(int x, int y) : _x(x), _y(y) {}
931 int _x, _y;
932 };
933 A *ptr = ut::new_arr_withkey<A>(UT_NEW_THIS_FILE_PSI_KEY,
934 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
935 std::forward_as_tuple(4, 5), std::forward_as_tuple(6, 7),
936 std::forward_as_tuple(8, 9));
937 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
938 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
939 assert(ptr[2]->_x == 4 && ptr[2]->_y == 5);
940 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
941 assert(ptr[4]->_x == 8 && ptr[4]->_y == 9);
942
943 Example 3:
944 struct A {
945 A() : _x(10), _y(100) {}
946 A(int x, int y) : _x(x), _y(y) {}
947 int _x, _y;
948 };
949 A *ptr = ut::new_arr_withkey<A>(UT_NEW_THIS_FILE_PSI_KEY,
950 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
951 std::forward_as_tuple(), std::forward_as_tuple(6, 7),
952 std::forward_as_tuple());
953 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
954 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
955 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
956 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
957 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
958 */
959template <typename T, typename... Args>
960inline T *new_arr(Args &&...args) {
961 return ut::new_arr_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
962 std::forward<Args>(args)...);
963}
964
965/** Light-weight and type-safe wrapper which serves a purpose of
966 being able to select proper ut::new_arr* overload.
967
968 Without having a separate overload with this type, creating an array of
969 default-initialized instances of T through the ut::new_arr*(Args &&... args)
970 overload would have been impossible because:
971 int *ptr = ut::new_arr_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY, 5);
972 wouldn't even compile and
973 int *ptr = ut::new_arr_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY,
974 std::forward_as_tuple(5)); would compile but would not have intended effect.
975 It would create an array holding 1 integer element that is initialized to 5.
976
977 Given that function templates cannot be specialized, having an overload
978 crafted specifically for given case solves the problem:
979 int *ptr = ut::new_arr_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY,
980 ut::Count{5});
981*/
982struct Count {
983 explicit Count(size_t count) : m_count(count) {}
984 size_t operator()() const { return m_count; }
985 size_t m_count;
986};
987
988/** Dynamically allocates storage for an array of T's. Constructs objects of
989 type T using default constructor. If T cannot be default-initialized (e.g.
990 default constructor does not exist), then this interface cannot be used for
991 constructing such an array. ut::new_arr_withkey overload with user-provided
992 initialization must be used then. Instruments the memory with given PSI
993 memory key in case PFS memory support is enabled.
994
995 @param[in] key PSI memory key to be used for PFS memory instrumentation.
996 @param[in] count Number of T elements in an array.
997 @return Pointer to the first element of allocated storage. Throws
998 std::bad_alloc exception if dynamic storage allocation could not be
999 fulfilled. Re-throws whatever exception that may have occurred during the
1000 construction of any instance of T, in which case it automatically destroys
1001 successfully constructed objects till that moment (if any), and finally
1002 cleans up the raw memory allocated for T instances.
1003
1004 Example 1:
1005 int *ptr = ut::new_arr_withkey<int>(key, ut::Count{2});
1006
1007 Example 2:
1008 struct A {
1009 A() : _x(10), _y(100) {}
1010 int _x, _y;
1011 };
1012 A *ptr = ut::new_arr_withkey<A>(key, ut::Count{5});
1013 assert(ptr[0]->_x == 10 && ptr[0]->_y == 100);
1014 assert(ptr[1]->_x == 10 && ptr[1]->_y == 100);
1015 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
1016 assert(ptr[3]->_x == 10 && ptr[3]->_y == 100);
1017 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
1018
1019 Example 3:
1020 struct A {
1021 A(int x, int y) : _x(x), _y(y) {}
1022 int _x, _y;
1023 };
1024 // Following cannot compile because A is not default-constructible
1025 A *ptr = ut::new_arr_withkey<A>(key, ut::Count{5});
1026 */
1027template <typename T>
1030 using malloc_impl = detail::Alloc_<impl>;
1031 auto mem = malloc_impl::alloc<false>(sizeof(T) * count(), key());
1032 if (unlikely(!mem)) throw std::bad_alloc();
1033
1034 size_t offset = 0;
1035 try {
1036 for (; offset < sizeof(T) * count(); offset += sizeof(T)) {
1037 new (reinterpret_cast<uint8_t *>(mem) + offset) T{};
1038 }
1039 } catch (...) {
1040 for (; offset != 0; offset -= sizeof(T)) {
1041 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(mem) + offset -
1042 sizeof(T))
1043 ->~T();
1044 }
1046 throw;
1047 }
1048 return static_cast<T *>(mem);
1049}
1050
1051/** Dynamically allocates storage for an array of T's. Constructs objects of
1052 type T using default constructor. If T cannot be default-initialized (e.g.
1053 default constructor does not exist), then this interface cannot be used for
1054 constructing such an array. ut::new_arr overload with user-provided
1055 initialization must be used then.
1056
1057 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1058 through PFS, observability for particular parts of the system which want to
1059 use it will be lost or in best case inaccurate. Please have a strong reason
1060 to do so.
1061
1062 @param[in] count Number of T elements in an array.
1063 @return Pointer to the first element of allocated storage. Throws
1064 std::bad_alloc exception if dynamic storage allocation could not be
1065 fulfilled. Re-throws whatever exception that may have occurred during the
1066 construction of any instance of T, in which case it automatically destroys
1067 successfully constructed objects till that moment (if any), and finally
1068 cleans up the raw memory allocated for T instances.
1069
1070 Example 1:
1071 int *ptr = ut::new_arr_withkey<int>(UT_NEW_THIS_FILE_PSI_KEY,
1072 ut::Count{2});
1073
1074 Example 2:
1075 struct A {
1076 A() : _x(10), _y(100) {}
1077 int _x, _y;
1078 };
1079 A *ptr = ut::new_arr_withkey<A>(UT_NEW_THIS_FILE_PSI_KEY, ut::Count{5});
1080 assert(ptr[0]->_x == 10 && ptr[0]->_y == 100);
1081 assert(ptr[1]->_x == 10 && ptr[1]->_y == 100);
1082 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
1083 assert(ptr[3]->_x == 10 && ptr[3]->_y == 100);
1084 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
1085
1086 Example 3:
1087 struct A {
1088 A(int x, int y) : _x(x), _y(y) {}
1089 int _x, _y;
1090 };
1091 // Following cannot compile because A is not default-constructible
1092 A *ptr = ut::new_arr_withkey<A>(UT_NEW_THIS_FILE_PSI_KEY, ut::Count{5});
1093 */
1094template <typename T>
1095inline T *new_arr(Count count) {
1096 return ut::new_arr_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
1097 count);
1098}
1099
1100/** Releases storage which has been dynamically allocated through any of
1101 the ut::new_arr*() variants. Destructs all objects of type T.
1102
1103 @param[in] ptr Pointer which has been obtained through any of the
1104 ut::new_arr*() variants
1105
1106 Example:
1107 ut::delete_arr(ptr);
1108 */
1109template <typename T>
1110inline void delete_arr(T *ptr) noexcept {
1111 if (unlikely(!ptr)) return;
1113 using malloc_impl = detail::Alloc_<impl>;
1114 const auto data_len = malloc_impl::datalen(ptr);
1115 for (size_t offset = 0; offset < data_len; offset += sizeof(T)) {
1116 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(ptr) + offset)->~T();
1117 }
1118 malloc_impl::free(ptr);
1119}
1120
1121/** Returns number of bytes that ut::malloc_*, ut::zalloc_*, ut::realloc_* and
1122 ut::new_* variants will be using to store the necessary metadata for PFS.
1123
1124 @return Size of the PFS metadata.
1125*/
1126inline size_t pfs_overhead() noexcept {
1128 using malloc_impl = detail::Alloc_<impl>;
1130}
1131
1132/** Dynamically allocates system page-aligned storage of given size. Instruments
1133 the memory with given PSI memory key in case PFS memory support is enabled.
1134
1135 Actual page-alignment, and thus page-size, will depend on CPU architecture
1136 but in general page is traditionally mostly 4K large. In contrast to Unices,
1137 Windows do make an exception here and implement 64K granularity on top of
1138 regular page-size for some legacy reasons. For more details see:
1139 https://devblogs.microsoft.com/oldnewthing/20031008-00/?p=42223
1140
1141 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1142 @param[in] size Size of storage (in bytes) requested to be allocated.
1143 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1144 allocation failed.
1145
1146 Example:
1147 int *x = static_cast<int*>(ut::malloc_page_withkey(key, 10*sizeof(int)));
1148 */
1150 std::size_t size) noexcept {
1152 using page_alloc_impl = detail::Page_alloc_<impl>;
1153 return page_alloc_impl::alloc(size, key());
1154}
1155
1156/** Dynamically allocates system page-aligned storage of given size.
1157
1158 Actual page-alignment, and thus page-size, will depend on CPU architecture
1159 but in general page is traditionally mostly 4K large. In contrast to Unices,
1160 Windows do make an exception here and implement 64K granularity on top of
1161 regular page-size for some legacy reasons. For more details see:
1162 https://devblogs.microsoft.com/oldnewthing/20031008-00/?p=42223
1163
1164 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1165 through PFS, observability for particular parts of the system which want to
1166 use it will be lost or in best case inaccurate. Please have a strong reason
1167 to do so.
1168
1169 @param[in] size Size of storage (in bytes) requested to be allocated.
1170 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1171 allocation failed.
1172
1173 Example:
1174 int *x = static_cast<int*>(ut::malloc_page(10*sizeof(int)));
1175 */
1176inline void *malloc_page(std::size_t size) noexcept {
1178 size);
1179}
1180
1181/** Retrieves the total amount of bytes that are available for application code
1182 to use.
1183
1184 Amount of bytes returned does _not_ have to match bytes requested
1185 through ut::malloc_page*(). This is so because bytes requested will always
1186 be implicitly rounded up to the next regular page size (e.g. 4K).
1187
1188 @param[in] ptr Pointer which has been obtained through any of the
1189 ut::malloc_page*() variants.
1190 @return Number of bytes available.
1191
1192 Example:
1193 int *x = static_cast<int*>(ut::malloc_page(10*sizeof(int)));
1194 assert(page_allocation_size(x) == CPU_PAGE_SIZE);
1195 */
1196inline size_t page_allocation_size(void *ptr) noexcept {
1198 using page_alloc_impl = detail::Page_alloc_<impl>;
1199 return page_alloc_impl::datalen(ptr);
1200}
1201
1202/** Retrieves the pointer and size of the allocation provided by the OS. It is a
1203 low level information, and is needed only to call low level memory-related
1204 OS functions.
1205
1206 @param[in] ptr Pointer which has been obtained through any of the
1207 ut::malloc_page*() variants.
1208 @return Low level OS allocation info.
1209 */
1212 using page_alloc_impl = detail::Page_alloc_<impl>;
1213 return page_alloc_impl::low_level_info(ptr);
1214}
1215
1216/** Releases storage which has been dynamically allocated through any of
1217 the ut::malloc_page*() variants.
1218
1219 @param[in] ptr Pointer which has been obtained through any of the
1220 ut::malloc_page*() variants.
1221 @return True if releasing the page-aligned memory was successful.
1222
1223 Example:
1224 ut::free_page(ptr);
1225 */
1226inline bool free_page(void *ptr) noexcept {
1228 using page_alloc_impl = detail::Page_alloc_<impl>;
1229 return page_alloc_impl::free(ptr);
1230}
1231
1232/** Dynamically allocates memory backed up by large (huge) pages. Instruments
1233 the memory with given PSI memory key in case PFS memory support is enabled.
1234
1235 For large (huge) pages to be functional, usually some steps in system admin
1236 preparation is required. Exact steps vary from system to system.
1237
1238 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1239 @param[in] size Size of storage (in bytes) requested to be allocated.
1240 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1241 allocation failed.
1242
1243 Example:
1244 int *x = static_cast<int*>(
1245 ut::malloc_large_page_withkey(key, 10*sizeof(int))
1246 );
1247 */
1249 std::size_t size) noexcept {
1251 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1252 return large_page_alloc_impl::alloc(size, key());
1253}
1254
1255/** Dynamically allocates memory backed up by large (huge) pages.
1256
1257 For large (huge) pages to be functional, usually some steps in system admin
1258 preparation is required. Exact steps vary from system to system.
1259
1260 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1261 through PFS, observability for particular parts of the system which want to
1262 use it will be lost or in best case inaccurate. Please have a strong reason
1263 to do so.
1264
1265 @param[in] size Size of storage (in bytes) requested to be allocated.
1266 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1267 allocation failed.
1268
1269 Example:
1270 int *x = static_cast<int*>(ut::malloc_large_page(10*sizeof(int)));
1271 */
1272inline void *malloc_large_page(std::size_t size) noexcept {
1275}
1276
1277/** Retrieves the total amount of bytes that are available for application code
1278 to use.
1279
1280 Amount of bytes returned does _not_ have to match bytes requested
1281 through ut::malloc_large_page*(). This is so because bytes requested will
1282 always be implicitly rounded up to the next multiple of huge-page size (e.g.
1283 2MiB). Exact huge-page size value that is going to be used will be stored
1284 in large_page_default_size.
1285
1286 @param[in] ptr Pointer which has been obtained through any of the
1287 ut::malloc_large_page*() variants.
1288 @return Number of bytes available.
1289
1290 Example:
1291 int *x = static_cast<int*>(ut::malloc_large_page(10*sizeof(int)));
1292 assert(large_page_allocation_size(x) == HUGE_PAGE_SIZE);
1293 */
1294inline size_t large_page_allocation_size(void *ptr) noexcept {
1296 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1297 return large_page_alloc_impl::datalen(ptr);
1298}
1299
1300/** Retrieves the pointer and size of the allocation provided by the OS. It is a
1301 low level information, and is needed only to call low level memory-related
1302 OS functions.
1303
1304 @param[in] ptr Pointer which has been obtained through any of the
1305 ut::malloc_large_page*() variants.
1306 @return Low level OS allocation info.
1307 */
1310 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1311 return large_page_alloc_impl::low_level_info(ptr);
1312}
1313
1314/** Releases storage which has been dynamically allocated through any of
1315 the ut::malloc_large_page*() variants.
1316
1317 @param[in] ptr Pointer which has been obtained through any of the
1318 ut::malloc_large_page*() variants.
1319 @return True if releasing the large (huge) page-aligned memory was
1320 successful.
1321
1322 Example:
1323 ut::free_large_page(ptr);
1324 */
1325inline bool free_large_page(void *ptr) noexcept {
1327 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1328 return large_page_alloc_impl::free(ptr);
1329}
1330
1331/* Helper type for tag-dispatch */
1333
1334/** Dynamically allocates memory backed up by large (huge) pages. In the event
1335 that large (huge) pages are unavailable or disabled explicitly through
1336 os_use_large_pages, it will fallback to dynamic allocation backed by
1337 page-aligned memory. Instruments the memory with given PSI memory key in
1338 case PFS memory support is enabled.
1339
1340 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1341 @param[in] size Size of storage (in bytes) requested to be allocated.
1342 @param[in] large_pages_enabled If true, the large pages will be tried to be
1343 used.
1344 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1345 allocation failed.
1346
1347 Example:
1348 int *x = static_cast<int*>(
1349 ut::malloc_large_page_withkey(
1350 key,
1351 10*sizeof(int),
1352 fallback_to_normal_page_t{}
1353 )
1354 );
1355 */
1358 bool large_pages_enabled = os_use_large_pages) noexcept {
1359 void *large_page_mem = nullptr;
1360 if (large_pages_enabled) {
1361 large_page_mem = malloc_large_page_withkey(key, size);
1362 }
1363 return large_page_mem ? large_page_mem : malloc_page_withkey(key, size);
1364}
1365
1366/** Dynamically allocates memory backed up by large (huge) pages. In the event
1367 that large (huge) pages are unavailable or disabled explicitly through
1368 os_use_large_pages, it will fallback to dynamic allocation backed by
1369 page-aligned memory.
1370
1371 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1372 through PFS, observability for particular parts of the system which want to
1373 use it will be lost or in best case inaccurate. Please have a strong reason
1374 to do so.
1375
1376 @param[in] size Size of storage (in bytes) requested to be allocated.
1377 @param[in] large_pages_enabled If true, the large pages will be tried to be
1378 used.
1379 @return Pointer to the page-aligned storage. nullptr if dynamic storage
1380 allocation failed.
1381
1382 Example:
1383 int *x = static_cast<int*>(
1384 ut::malloc_large_page(
1385 10*sizeof(int),
1386 fallback_to_normal_page_t{}
1387 )
1388 );
1389 */
1391 std::size_t size, fallback_to_normal_page_t,
1392 bool large_pages_enabled = os_use_large_pages) noexcept {
1395 fallback_to_normal_page_t{}, large_pages_enabled);
1396}
1397
1398/** Retrieves the total amount of bytes that are available for application code
1399 to use.
1400
1401 Amount of bytes returned does _not_ have to match bytes requested
1402 through ut::malloc_large_page*(fallback_to_normal_page_t). This is so
1403 because bytes requested will always be implicitly rounded up to the next
1404 multiple of either huge-page size (e.g. 2MiB) or regular page size (e.g.
1405 4K).
1406
1407 @param[in] ptr Pointer which has been obtained through any of the
1408 ut::malloc_large_page*(fallback_to_normal_page_t) variants.
1409 @return Number of bytes available for use.
1410 */
1411inline size_t large_page_allocation_size(void *ptr,
1412 fallback_to_normal_page_t) noexcept {
1413 assert(ptr);
1415 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1416 if (large_page_alloc_impl::page_type(ptr) == detail::Page_type::system_page)
1417 return ut::page_allocation_size(ptr);
1418 ut_a(large_page_alloc_impl::page_type(ptr) == detail::Page_type::large_page);
1420}
1421
1422/** Retrieves the pointer and size of the allocation provided by the OS. It is a
1423 low level information, and is needed only to call low level memory-related
1424 OS functions.
1425
1426 @param[in] ptr Pointer which has been obtained through any of the
1427 ut::malloc_large_page*(fallback_to_normal_page_t) variants.
1428 @return Low level OS allocation info.
1429 */
1431 void *ptr, fallback_to_normal_page_t) noexcept {
1432 assert(ptr);
1434 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1435 if (large_page_alloc_impl::page_type(ptr) == detail::Page_type::system_page)
1436 return ut::page_low_level_info(ptr);
1437 ut_a(large_page_alloc_impl::page_type(ptr) == detail::Page_type::large_page);
1439}
1440
1441/** Releases storage which has been dynamically allocated through any of
1442 the ut::malloc_large_page*(fallback_to_normal_page_t) variants.
1443
1444 Whether the pointer is representing area backed up by regular or huge-pages,
1445 this function will know the difference and therefore act accordingly.
1446
1447 @param[in] ptr Pointer which has been obtained through any of the
1448 ut::malloc_large_page*(fallback_to_normal_page_t) variants.
1449 @return True if releasing the memory was successful.
1450
1451 Example:
1452 ut::free_large_page(ptr);
1453 */
1454inline bool free_large_page(void *ptr, fallback_to_normal_page_t) noexcept {
1456 using large_page_alloc_impl = detail::Large_alloc_<impl>;
1457
1458 if (!ptr) return false;
1459
1460 bool success;
1461 if (large_page_alloc_impl::page_type(ptr) == detail::Page_type::system_page) {
1462 success = free_page(ptr);
1463 } else {
1464 ut_a(large_page_alloc_impl::page_type(ptr) ==
1466 success = free_large_page(ptr);
1467 }
1468 assert(success);
1469 return success;
1470}
1471
1472/** Dynamically allocates storage of given size and at the address aligned to
1473 the requested alignment. Instruments the memory with given PSI memory key
1474 in case PFS memory support is enabled.
1475
1476 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1477 @param[in] size Size of storage (in bytes) requested to be allocated.
1478 @param[in] alignment Alignment requirement for storage to be allocated.
1479 @return Pointer to the allocated storage. nullptr if dynamic storage
1480 allocation failed.
1481
1482 Example:
1483 int* x = static_cast<int*>(aligned_alloc_withkey(key, 10*sizeof(int), 64));
1484 */
1485inline void *aligned_alloc_withkey(PSI_memory_key_t key, std::size_t size,
1486 std::size_t alignment) noexcept {
1488 using aligned_alloc_impl = detail::Aligned_alloc_<impl>;
1489 return aligned_alloc_impl::alloc<false>(size, alignment, key());
1490}
1491
1492/** Dynamically allocates storage of given size and at the address aligned to
1493 the requested alignment.
1494
1495 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1496 through PFS, observability for particular parts of the system which want to
1497 use it will be lost or in best case inaccurate. Please have a strong reason
1498 to do so.
1499
1500 @param[in] size Size of storage (in bytes) requested to be allocated.
1501 @param[in] alignment Alignment requirement for storage to be allocated.
1502 @return Pointer to the allocated storage. nullptr if dynamic storage
1503 allocation failed.
1504
1505 Example:
1506 int* x = static_cast<int*>(aligned_alloc(10*sizeof(int), 64));
1507 */
1508inline void *aligned_alloc(std::size_t size, std::size_t alignment) noexcept {
1510 alignment);
1511}
1512
1513/** Dynamically allocates zero-initialized storage of given size and at the
1514 address aligned to the requested alignment. Instruments the memory with
1515 given PSI memory key in case PFS memory support is enabled.
1516
1517 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1518 @param[in] size Size of storage (in bytes) requested to be allocated.
1519 @param[in] alignment Alignment requirement for storage to be allocated.
1520 @return Pointer to the zero-initialized allocated storage. nullptr if
1521 dynamic storage allocation failed.
1522
1523 Example:
1524 int* x =
1525 static_cast<int*>(aligned_zalloc_withkey(key, 10*sizeof(int), 64));
1526 */
1527inline void *aligned_zalloc_withkey(PSI_memory_key_t key, std::size_t size,
1528 std::size_t alignment) noexcept {
1530 using aligned_alloc_impl = detail::Aligned_alloc_<impl>;
1531 return aligned_alloc_impl::alloc<true>(size, alignment, key());
1532}
1533
1534/** Dynamically allocates zero-initialized storage of given size and at the
1535 address aligned to the requested alignment.
1536
1537 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1538 through PFS, observability for particular parts of the system which want to
1539 use it will be lost or in best case inaccurate. Please have a strong reason
1540 to do so.
1541
1542 @param[in] size Size of storage (in bytes) requested to be allocated.
1543 @param[in] alignment Alignment requirement for storage to be allocated.
1544 @return Pointer to the zero-initialized allocated storage. nullptr if
1545 dynamic storage allocation failed.
1546
1547 Example:
1548 int* x = static_cast<int*>(aligned_zalloc(10*sizeof(int), 64));
1549 */
1550inline void *aligned_zalloc(std::size_t size, std::size_t alignment) noexcept {
1552 alignment);
1553}
1554
1555/** Releases storage which has been dynamically allocated through any of
1556 the aligned_alloc_*() or aligned_zalloc_*() variants.
1557
1558 @param[in] ptr Pointer which has been obtained through any of the
1559 aligned_alloc_*() or aligned_zalloc_*() variants.
1560
1561 Example:
1562 aligned_free(ptr);
1563 */
1564inline void aligned_free(void *ptr) noexcept {
1566 using aligned_alloc_impl = detail::Aligned_alloc_<impl>;
1568}
1569
1570/** Dynamically allocates storage for an object of type T at address aligned
1571 to the requested alignment. Constructs the object of type T with provided
1572 Args. Instruments the memory with given PSI memory key in case PFS memory
1573 support is enabled.
1574
1575 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1576 @param[in] alignment Alignment requirement for storage to be allocated.
1577 @param[in] args Arguments one wishes to pass over to T constructor(s)
1578 @return Pointer to the allocated storage. Throws std::bad_alloc exception
1579 if dynamic storage allocation could not be fulfilled.
1580
1581 Example 1:
1582 int *ptr = aligned_new_withkey<int>(key, 2);
1583
1584 Example 2:
1585 int *ptr = aligned_new_withkey<int>(key, 2, 10);
1586 assert(*ptr == 10);
1587
1588 Example 3:
1589 struct A { A(int x, int y) : _x(x), _y(y) {} int x, y; }
1590 A *ptr = aligned_new_withkey<A>(key, 2, 1, 2);
1591 assert(ptr->x == 1);
1592 assert(ptr->y == 2);
1593 */
1594template <typename T, typename... Args>
1595inline T *aligned_new_withkey(PSI_memory_key_t key, std::size_t alignment,
1596 Args &&...args) {
1597 auto mem = aligned_alloc_withkey(key, sizeof(T), alignment);
1598 if (unlikely(!mem)) throw std::bad_alloc();
1599 try {
1600 new (mem) T(std::forward<Args>(args)...);
1601 } catch (...) {
1603 throw;
1604 }
1605 return static_cast<T *>(mem);
1606}
1607
1608/** Dynamically allocates storage for an object of type T at address aligned
1609 to the requested alignment. Constructs the object of type T with provided
1610 Args.
1611
1612 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1613 through PFS, observability for particular parts of the system which want to
1614 use it will be lost or in best case inaccurate. Please have a strong reason
1615 to do so.
1616
1617 @param[in] alignment Alignment requirement for storage to be allocated.
1618 @param[in] args Arguments one wishes to pass over to T constructor(s)
1619 @return Pointer to the allocated storage. Throws std::bad_alloc exception
1620 if dynamic storage allocation could not be fulfilled.
1621
1622 Example 1:
1623 int *ptr = aligned_new<int>(2);
1624
1625 Example 2:
1626 int *ptr = aligned_new<int>(2, 10);
1627 assert(*ptr == 10);
1628
1629 Example 3:
1630 struct A { A(int x, int y) : _x(x), _y(y) {} int x, y; }
1631 A *ptr = aligned_new<A>(2, 1, 2);
1632 assert(ptr->x == 1);
1633 assert(ptr->y == 2);
1634 */
1635template <typename T, typename... Args>
1636inline T *aligned_new(std::size_t alignment, Args &&...args) {
1637 return aligned_new_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
1638 alignment, std::forward<Args>(args)...);
1639}
1640
1641/** Releases storage which has been dynamically allocated through any of
1642 the aligned_new_*() variants. Destructs the object of type T.
1643
1644 @param[in] ptr Pointer which has been obtained through any of the
1645 aligned_new_*() variants
1646
1647 Example:
1648 aligned_delete(ptr);
1649 */
1650template <typename T>
1651inline void aligned_delete(T *ptr) noexcept {
1652 ptr->~T();
1653 aligned_free(ptr);
1654}
1655
1656/** Dynamically allocates storage for an array of T's at address aligned to the
1657 requested alignment. Constructs objects of type T with provided Args.
1658 Arguments that are to be used to construct some respective instance of T
1659 shall be wrapped into a std::tuple. See examples down below. Instruments the
1660 memory with given PSI memory key in case PFS memory support is enabled.
1661
1662 To create an array of default-initialized T's, one can use this function
1663 template but for convenience purposes one can achieve the same by using
1664 the ut::aligned_new_arr_withkey with ut::Count overload.
1665
1666 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1667 @param[in] alignment Alignment requirement for storage to be allocated.
1668 @param[in] args Tuples of arguments one wishes to pass over to T
1669 constructor(s).
1670 @return Pointer to the first element of allocated storage. Throws
1671 std::bad_alloc exception if dynamic storage allocation could not be
1672 fulfilled. Re-throws whatever exception that may have occurred during the
1673 construction of any instance of T, in which case it automatically destroys
1674 successfully constructed objects till that moment (if any), and finally
1675 cleans up the raw memory allocated for T instances.
1676
1677 Example 1:
1678 int *ptr = ut::aligned_new_arr_withkey<int>(key, 32,
1679 std::forward_as_tuple(1),
1680 std::forward_as_tuple(2));
1681 assert(ptr[0] == 1);
1682 assert(ptr[1] == 2);
1683
1684 Example 2:
1685 struct A {
1686 A(int x, int y) : _x(x), _y(y) {}
1687 int _x, _y;
1688 };
1689 A *ptr = ut::aligned_new_arr_withkey<A>(key, 32,
1690 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
1691 std::forward_as_tuple(4, 5), std::forward_as_tuple(6, 7),
1692 std::forward_as_tuple(8, 9));
1693 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
1694 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
1695 assert(ptr[2]->_x == 4 && ptr[2]->_y == 5);
1696 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
1697 assert(ptr[4]->_x == 8 && ptr[4]->_y == 9);
1698
1699 Example 3:
1700 struct A {
1701 A() : _x(10), _y(100) {}
1702 A(int x, int y) : _x(x), _y(y) {}
1703 int _x, _y;
1704 };
1705 A *ptr = ut::aligned_new_arr_withkey<A>(key, 32,
1706 std::forward_as_tuple(0, 1), std::forward_as_tuple(2, 3),
1707 std::forward_as_tuple(), std::forward_as_tuple(6, 7),
1708 std::forward_as_tuple());
1709 assert(ptr[0]->_x == 0 && ptr[0]->_y == 1);
1710 assert(ptr[1]->_x == 2 && ptr[1]->_y == 3);
1711 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
1712 assert(ptr[3]->_x == 6 && ptr[3]->_y == 7);
1713 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
1714 */
1715template <typename T, typename... Args>
1716inline T *aligned_new_arr_withkey(PSI_memory_key_t key, std::size_t alignment,
1717 Args &&...args) {
1718 auto mem = aligned_alloc_withkey(key, sizeof(T) * sizeof...(args), alignment);
1719 if (unlikely(!mem)) throw std::bad_alloc();
1720
1721 size_t idx = 0;
1722 try {
1723 (...,
1724 detail::construct<T>(mem, sizeof(T) * idx++, std::forward<Args>(args)));
1725 } catch (...) {
1726 for (size_t offset = (idx - 1) * sizeof(T); offset != 0;
1727 offset -= sizeof(T)) {
1728 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(mem) + offset -
1729 sizeof(T))
1730 ->~T();
1731 }
1733 throw;
1734 }
1735 return static_cast<T *>(mem);
1736}
1737
1738/** Dynamically allocates storage for an array of T's at address aligned to the
1739 requested alignment. Constructs objects of type T using default constructor.
1740 If T cannot be default-initialized (e.g. default constructor does not
1741 exist), then this interface cannot be used for constructing such an array.
1742 ut::new_arr_withkey overload with user-provided initialization must be used
1743 then. Instruments the memory with given PSI memory key in case PFS memory
1744 support is enabled.
1745
1746 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1747 @param[in] alignment Alignment requirement for storage to be allocated.
1748 @param[in] count Number of T elements in an array.
1749 @return Pointer to the first element of allocated storage. Throws
1750 std::bad_alloc exception if dynamic storage allocation could not be
1751 fulfilled. Re-throws whatever exception that may have occurred during the
1752 construction of any instance of T, in which case it automatically destroys
1753 successfully constructed objects till that moment (if any), and finally
1754 cleans up the raw memory allocated for T instances.
1755
1756 Example 1:
1757 int *ptr = ut::aligned_new_arr_withkey<int>(key, 32, ut::Count{2});
1758
1759 Example 2:
1760 struct A {
1761 A() : _x(10), _y(100) {}
1762 int _x, _y;
1763 };
1764 A *ptr = ut::aligned_new_arr_withkey<A>(key, 32, ut::Count{5});
1765 assert(ptr[0]->_x == 10 && ptr[0]->_y == 100);
1766 assert(ptr[1]->_x == 10 && ptr[1]->_y == 100);
1767 assert(ptr[2]->_x == 10 && ptr[2]->_y == 100);
1768 assert(ptr[3]->_x == 10 && ptr[3]->_y == 100);
1769 assert(ptr[4]->_x == 10 && ptr[4]->_y == 100);
1770
1771 Example 3:
1772 struct A {
1773 A(int x, int y) : _x(x), _y(y) {}
1774 int _x, _y;
1775 };
1776 // Following cannot compile because A is not default-constructible
1777 A *ptr = ut::aligned_new_arr_withkey<A>(key, 32, ut::Count{5});
1778 */
1779template <typename T>
1780inline T *aligned_new_arr_withkey(PSI_memory_key_t key, std::size_t alignment,
1781 Count count) {
1782 auto mem = aligned_alloc_withkey(key, sizeof(T) * count(), alignment);
1783 if (unlikely(!mem)) throw std::bad_alloc();
1784
1785 size_t offset = 0;
1786 try {
1787 for (; offset < sizeof(T) * count(); offset += sizeof(T)) {
1788 new (reinterpret_cast<uint8_t *>(mem) + offset) T{};
1789 }
1790 } catch (...) {
1791 for (; offset != 0; offset -= sizeof(T)) {
1792 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(mem) + offset -
1793 sizeof(T))
1794 ->~T();
1795 }
1797 throw;
1798 }
1799 return static_cast<T *>(mem);
1800}
1801
1802/** Dynamically allocates storage for an array of T's at address aligned to
1803 the requested alignment. Constructs objects of type T with provided Args.
1804
1805 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1806 through PFS, observability for particular parts of the system which want to
1807 use it will be lost or in best case inaccurate. Please have a strong reason
1808 to do so.
1809
1810 @param[in] alignment Alignment requirement for storage to be allocated.
1811 @param[in] args Arguments one wishes to pass over to T constructor(s)
1812 @return Pointer to the first element of allocated storage. Throws
1813 std::bad_alloc exception if dynamic storage allocation could not be
1814 fulfilled.
1815
1816 Example 1:
1817 int *ptr = aligned_new_arr<int, 5>(2);
1818 ptr[0] ... ptr[4]
1819
1820 Example 2:
1821 int *ptr = aligned_new_arr<int, 5>(2, 1, 2, 3, 4, 5);
1822 assert(*ptr[0] == 1);
1823 assert(*ptr[1] == 2);
1824 ...
1825 assert(*ptr[4] == 5);
1826
1827 Example 3:
1828 struct A { A(int x, int y) : _x(x), _y(y) {} int x, y; }
1829 A *ptr = aligned_new_arr<A, 5>(2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
1830 assert(ptr[0]->x == 1);
1831 assert(ptr[0]->y == 2);
1832 assert(ptr[1]->x == 3);
1833 assert(ptr[1]->y == 4);
1834 ...
1835 assert(ptr[4]->x == 9);
1836 assert(ptr[4]->y == 10);
1837 */
1838template <typename T, typename... Args>
1839inline T *aligned_new_arr(std::size_t alignment, Args &&...args) {
1840 return aligned_new_arr_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
1841 alignment, std::forward<Args>(args)...);
1842}
1843
1844/** Dynamically allocates storage for an array of T's at address aligned to
1845 the requested alignment. Constructs objects of type T using default
1846 constructor.
1847
1848 NOTE: Given that this function will _NOT_ be instrumenting the allocation
1849 through PFS, observability for particular parts of the system which want to
1850 use it will be lost or in best case inaccurate. Please have a strong reason
1851 to do so.
1852
1853 @param[in] alignment Alignment requirement for storage to be allocated.
1854 @param[in] count Number of T elements in an array.
1855 @return Pointer to the first element of allocated storage. Throws
1856 std::bad_alloc exception if dynamic storage allocation could not be
1857 fulfilled.
1858
1859 Example 1:
1860 int *ptr = aligned_new_arr<int>(2, 5);
1861 assert(*ptr[0] == 0);
1862 assert(*ptr[1] == 0);
1863 ...
1864 assert(*ptr[4] == 0);
1865
1866 Example 2:
1867 struct A { A) : x(1), y(2) {} int x, y; }
1868 A *ptr = aligned_new_arr<A>(2, 5);
1869 assert(ptr[0].x == 1);
1870 assert(ptr[0].y == 2);
1871 ...
1872 assert(ptr[4].x == 1);
1873 assert(ptr[4].y == 2);
1874
1875 Example 3:
1876 struct A { A(int x, int y) : _x(x), _y(y) {} int x, y; }
1877 A *ptr = aligned_new_arr<A>(2, 5);
1878 // will not compile, no default constructor
1879 */
1880template <typename T>
1881inline T *aligned_new_arr(std::size_t alignment, Count count) {
1882 return aligned_new_arr_withkey<T>(make_psi_memory_key(PSI_NOT_INSTRUMENTED),
1883 alignment, count);
1884}
1885
1886/** Releases storage which has been dynamically allocated through any of the
1887 aligned_new_arr_*() variants. Destructs all objects of type T.
1888
1889 @param[in] ptr Pointer which has been obtained through any of the
1890 aligned_new_arr_*() variants.
1891
1892 Example:
1893 aligned_delete_arr(ptr);
1894 */
1895template <typename T>
1896inline void aligned_delete_arr(T *ptr) noexcept {
1898 using aligned_alloc_impl = detail::Aligned_alloc_<impl>;
1899 const auto data_len = aligned_alloc_impl::datalen(ptr);
1900 for (size_t offset = 0; offset < data_len; offset += sizeof(T)) {
1901 reinterpret_cast<T *>(reinterpret_cast<std::uintptr_t>(ptr) + offset)->~T();
1902 }
1903 aligned_free(ptr);
1904}
1905
1906/** Lightweight convenience wrapper which manages dynamically allocated
1907 over-aligned type. Wrapper makes use of RAII to do the resource cleanup.
1908
1909 Example usage:
1910 struct My_fancy_type {
1911 My_fancy_type(int x, int y) : _x(x), _y(y) {}
1912 int _x, _y;
1913 };
1914
1915 aligned_pointer<My_fancy_type, 32> ptr;
1916 ptr.alloc(10, 5);
1917 My_fancy_type *p = ptr;
1918 assert(p->_x == 10 && p->_y == 5);
1919
1920 @tparam T Type to be managed.
1921 @tparam Alignment Number of bytes to align the type T to.
1922 */
1923template <typename T, size_t Alignment>
1925 T *ptr = nullptr;
1926
1927 public:
1928 /** Destructor. Invokes destructor of the underlying instance of
1929 type T. Releases dynamically allocated resources, if there had been
1930 left any.
1931 */
1933 if (ptr) dealloc();
1934 }
1935
1936 /** Allocates sufficiently large memory of dynamic storage duration to fit
1937 the instance of type T at the address which is aligned to Alignment bytes.
1938 Constructs the instance of type T with given Args.
1939
1940 Underlying instance of type T is accessed through the conversion operator.
1941
1942 @param[in] args Any number and type of arguments that type T can be
1943 constructed with.
1944 */
1945 template <typename... Args>
1946 void alloc(Args &&...args) {
1947 ut_ad(ptr == nullptr);
1948 ptr = ut::aligned_new<T>(Alignment, args...);
1949 }
1950
1951 /** Allocates sufficiently large memory of dynamic storage duration to fit
1952 the instance of type T at the address which is aligned to Alignment bytes.
1953 Constructs the instance of type T with given Args. Instruments the memory
1954 with given PSI memory key in case PFS memory support is enabled.
1955
1956 Underlying instance of type T is accessed through the conversion operator.
1957
1958 @param[in] key PSI memory key to be used for PFS memory instrumentation.
1959 @param[in] args Any number and type of arguments that type T can be
1960 constructed with.
1961 */
1962 template <typename... Args>
1963 void alloc_withkey(PSI_memory_key_t key, Args &&...args) {
1964 ut_ad(ptr == nullptr);
1965 ptr =
1966 ut::aligned_new_withkey<T>(key, Alignment, std::forward<Args>(args)...);
1967 }
1968
1969 /** Invokes the destructor of instance of type T, if applicable.
1970 Releases the resources previously allocated with alloc().
1971 */
1972 void dealloc() {
1973 ut_ad(ptr != nullptr);
1975 ptr = nullptr;
1976 }
1977
1978 /** Conversion operator. Used for accessing the underlying instance of
1979 type T.
1980 */
1981 operator T *() const {
1982 ut_ad(ptr != nullptr);
1983 return ptr;
1984 }
1985};
1986
1987/** Lightweight convenience wrapper which manages a dynamically
1988 allocated array of over-aligned types. Only the first element of an array is
1989 guaranteed to be aligned to the requested Alignment. Wrapper makes use of
1990 RAII to do the resource cleanup.
1991
1992 Example usage 1:
1993 struct My_fancy_type {
1994 My_fancy_type() : _x(0), _y(0) {}
1995 My_fancy_type(int x, int y) : _x(x), _y(y) {}
1996 int _x, _y;
1997 };
1998
1999 aligned_array_pointer<My_fancy_type, 32> ptr;
2000 ptr.alloc(3);
2001 My_fancy_type *p = ptr;
2002 assert(p[0]._x == 0 && p[0]._y == 0);
2003 assert(p[1]._x == 0 && p[1]._y == 0);
2004 assert(p[2]._x == 0 && p[2]._y == 0);
2005
2006 Example usage 2:
2007 aligned_array_pointer<My_fancy_type, 32> ptr;
2008 ptr.alloc<3>(1, 2, 3, 4, 5, 6);
2009 My_fancy_type *p = ptr;
2010 assert(p[0]._x == 1 && p[0]._y == 2);
2011 assert(p[1]._x == 3 && p[1]._y == 4);
2012 assert(p[2]._x == 5 && p[2]._y == 6);
2013
2014 @tparam T Type to be managed.
2015 @tparam Alignment Number of bytes to align the first element of array to.
2016 */
2017template <typename T, size_t Alignment>
2019 T *ptr = nullptr;
2020
2021 public:
2022 /** Destructor. Invokes destructors of the underlying instances of
2023 type T. Releases dynamically allocated resources, if there had been
2024 left any.
2025 */
2027 if (ptr) dealloc();
2028 }
2029
2030 /** Allocates sufficiently large memory of dynamic storage duration to fit
2031 the array of size number of elements of type T at the address which is
2032 aligned to Alignment bytes. Constructs the size number of instances of
2033 type T, each being initialized through the means of default constructor.
2034
2035 Underlying instances of type T are accessed through the conversion
2036 operator.
2037
2038 @param[in] count Number of T elements in an array.
2039 */
2041 ut_ad(ptr == nullptr);
2042 ptr = ut::aligned_new_arr<T>(Alignment, count);
2043 }
2044
2045 /** Allocates sufficiently large memory of dynamic storage duration to fit
2046 the array of size number of elements of type T at the address which is
2047 aligned to Alignment bytes. Constructs the size number of instances of
2048 type T, each being initialized through the means of provided Args and
2049 corresponding constructors.
2050
2051 Underlying instances of type T are accessed through the conversion
2052 operator.
2053
2054 @param[in] args Any number and type of arguments that type T can be
2055 constructed with.
2056 */
2057 template <typename... Args>
2058 void alloc(Args &&...args) {
2059 ut_ad(ptr == nullptr);
2060 ptr = ut::aligned_new_arr<T>(Alignment, std::forward<Args>(args)...);
2061 }
2062
2063 /** Allocates sufficiently large memory of dynamic storage duration to fit
2064 the array of size number of elements of type T at the address which is
2065 aligned to Alignment bytes. Constructs the size number of instances of
2066 type T, each being initialized through the means of default constructor.
2067 Instruments the memory with given PSI memory key in case PFS memory
2068 support is enabled.
2069
2070 Underlying instances of type T are accessed through the conversion
2071 operator.
2072
2073 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2074 @param[in] count Number of T elements in an array.
2075 */
2077 ut_ad(ptr == nullptr);
2078 ptr = ut::aligned_new_arr_withkey<T>(key, Alignment, count);
2079 }
2080
2081 /** Allocates sufficiently large memory of dynamic storage duration to fit
2082 the array of size number of elements of type T at the address which is
2083 aligned to Alignment bytes. Constructs the size number of instances of
2084 type T, each being initialized through the means of provided Args and
2085 corresponding constructors. Instruments the memory with given PSI memory
2086 key in case PFS memory support is enabled.
2087
2088 Underlying instances of type T are accessed through the conversion
2089 operator.
2090
2091 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2092 @param[in] args Any number and type of arguments that type T can be
2093 constructed with.
2094 */
2095 template <typename... Args>
2096 void alloc_withkey(PSI_memory_key_t key, Args &&...args) {
2097 ut_ad(ptr == nullptr);
2098 ptr = ut::aligned_new_arr_withkey<T>(key, Alignment,
2099 std::forward<Args>(args)...);
2100 }
2101
2102 /** Invokes destructors of instances of type T, if applicable.
2103 Releases the resources previously allocated with any variant of
2104 alloc().
2105 */
2106 void dealloc() {
2108 ptr = nullptr;
2109 }
2110
2111 /** Conversion operator. Used for accessing the underlying instances of
2112 type T.
2113 */
2114 operator T *() const {
2115 ut_ad(ptr != nullptr);
2116 return ptr;
2117 }
2118};
2119
2120namespace detail {
2121template <typename T>
2123 explicit allocator_base(PSI_memory_key /*key*/) {}
2124
2125 template <typename U>
2127
2128 void *allocate_impl(size_t n_bytes) { return ut::malloc(n_bytes); }
2129};
2130
2131template <typename T>
2134
2135 template <typename U>
2137 : allocator_base_pfs(other.get_mem_key()) {}
2138
2140
2141 void *allocate_impl(size_t n_bytes) {
2143 }
2144
2145 private:
2147};
2148} // namespace detail
2149
2150/** Allocator that allows std::* containers to manage their memory through
2151 ut::malloc* and ut::free library functions.
2152
2153 Main purpose of this custom allocator is to instrument all of the memory
2154 allocations and deallocations that are being done by std::* containers under
2155 the hood, and have them recorded through the PFS (memory) engine.
2156
2157 Other than std::* containers, this allocator is of course also suitable for
2158 use in any other allocator-aware containers and/or code.
2159
2160 Given that ut::malloc* and ut::free library functions already handle all
2161 the PFS and non-PFS implementation bits and pieces, this allocator is a mere
2162 wrapper around them.
2163
2164 Example which uses default PFS key (mem_key_std) to trace all std::vector
2165 allocations and deallocations:
2166 std::vector<int, ut::allocator<int>> vec;
2167 vec.push_back(...);
2168 ...
2169 vec.push_back(...);
2170
2171 Example which uses user-provided PFS key to trace std::vector allocations
2172 and deallocations:
2173 ut::allocator<int> allocator(some_other_psi_key);
2174 std::vector<int, ut::allocator<int>> vec(allocator);
2175 vec.push_back(...);
2176 ...
2177 vec.push_back(...);
2178 */
2179template <typename T, typename Allocator_base = std::conditional_t<
2182class allocator : public Allocator_base {
2183 public:
2184 using pointer = T *;
2185 using const_pointer = const T *;
2186 using reference = T &;
2187 using const_reference = const T &;
2188 using value_type = T;
2189 using size_type = size_t;
2190 using difference_type = ptrdiff_t;
2191
2192 static_assert(alignof(T) <= alignof(std::max_align_t),
2193 "ut::allocator does not support over-aligned types. Use "
2194 "ut::aligned_* API to handle such types.");
2195
2196 /** Default constructor, use mem_key_std.
2197 */
2198 allocator() : Allocator_base(mem_key_std) {}
2199
2200 /** Explicit constructor.
2201 @param[in] key performance schema key.
2202 */
2203 explicit allocator(PSI_memory_key key) : Allocator_base(key) {}
2204
2205 /* Rule-of-five */
2208 const allocator<T, Allocator_base> &) = default;
2211 default;
2212 ~allocator() = default;
2213
2214 /** Copy-construct a new instance of allocator with type T by using existing
2215 instance of allocator constructed with a different type U.
2216 @param[in] other the allocator to copy from.
2217 */
2218 template <typename U>
2220 : Allocator_base(other) {}
2221
2222 /* NOTE: rebind is deprecated in C++17 and to be removed in C++20 but one of
2223 our toolchains, when used in 32-bit setting, still does not support custom
2224 allocators that do not provide rebind support explicitly. In future, this
2225 part will become redundant and can be removed.
2226 */
2227 template <typename U>
2228 struct rebind {
2230 };
2231
2232 /** Equality of allocators instantiated with same types T. */
2234 return true;
2235 }
2236 /** Non-equality of allocators instantiated with same types T. */
2237 inline bool operator!=(const ut::allocator<T, Allocator_base> &other) const {
2238 return !(*this == other);
2239 }
2240
2241 /** Return the maximum number of objects that can be allocated by
2242 this allocator. This number is somewhat lower for PFS-enabled
2243 builds because of extra few bytes needed for PFS.
2244 */
2246 const size_type s_max = std::numeric_limits<size_type>::max();
2247 return (s_max - ut::pfs_overhead()) / sizeof(T);
2248 }
2249
2250 /** Allocates chunk of memory that can hold n_elements objects of
2251 type T. Returned pointer is always valid. In case underlying
2252 allocation function was not able to fulfill the allocation request,
2253 this function will throw std::bad_alloc exception. After successful
2254 allocation, returned pointer must be passed back to
2255 ut::allocator<T>::deallocate() when no longer needed.
2256
2257 @param[in] n_elements number of elements
2258 @param[in] hint pointer to a nearby memory location,
2259 not used by this implementation
2260 @return pointer to the allocated memory
2261 */
2263 const_pointer hint [[maybe_unused]] = nullptr) {
2264 if (unlikely(n_elements > max_size())) {
2265 throw std::bad_array_new_length();
2266 }
2267
2268 auto ptr = Allocator_base::allocate_impl(n_elements * sizeof(T));
2269
2270 if (unlikely(!ptr)) {
2271 throw std::bad_alloc();
2272 }
2273
2274 return static_cast<pointer>(ptr);
2275 }
2276
2277 /** Releases the memory allocated through ut::allocator<T>::allocate().
2278
2279 @param[in,out] ptr pointer to memory to free
2280 @param[in] n_elements number of elements allocated (unused)
2281 */
2282 void deallocate(pointer ptr, size_type n_elements [[maybe_unused]] = 0) {
2283 ut::free(ptr);
2284 }
2285};
2286
2287namespace detail {
2288template <typename>
2289constexpr bool is_unbounded_array_v = false;
2290template <typename T>
2291constexpr bool is_unbounded_array_v<T[]> = true;
2292
2293template <typename>
2294constexpr bool is_bounded_array_v = false;
2295template <typename T, std::size_t N>
2296constexpr bool is_bounded_array_v<T[N]> = true;
2297
2298template <typename>
2299constexpr size_t bounded_array_size_v = 0;
2300template <typename T, std::size_t N>
2302
2303template <typename T>
2304struct Deleter {
2305 void operator()(T *ptr) { ut::delete_(ptr); }
2306};
2307
2308template <typename T>
2310 void operator()(T *ptr) { ut::delete_arr(ptr); }
2311};
2312
2313template <typename T>
2315 void operator()(T *ptr) { ut::aligned_delete(ptr); }
2316};
2317
2318template <typename T>
2320 void operator()(T *ptr) { ut::aligned_delete_arr(ptr); }
2321};
2322
2323} // namespace detail
2324
2325/** Dynamically allocates storage for an object of type T. Constructs the object
2326 of type T with provided Args. Wraps the pointer to T instance into the
2327 std::unique_ptr.
2328
2329 This overload participates in overload resolution only if T
2330 is not an array type.
2331
2332 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2333 through PFS, observability for particular parts of the system which want to
2334 use it will be lost or in best case inaccurate. Please have a strong reason
2335 to do so.
2336
2337 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2338 @return std::unique_ptr holding a pointer to instance of T.
2339 */
2340template <typename T, typename Deleter = detail::Deleter<T>, typename... Args>
2341std::enable_if_t<!std::is_array<T>::value, std::unique_ptr<T, Deleter>>
2342make_unique(Args &&...args) {
2343 return std::unique_ptr<T, Deleter>(ut::new_<T>(std::forward<Args>(args)...));
2344}
2345
2346/** Dynamically allocates storage for an object of type T. Constructs the object
2347 of type T with provided Args. Wraps the pointer to T instance into the
2348 std::unique_ptr with custom deleter which knows how to handle PFS-enabled
2349 dynamic memory allocations. Instruments the memory with given PSI memory key
2350 in case PFS memory support is enabled.
2351
2352 This overload participates in overload resolution only if T
2353 is not an array type.
2354
2355 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2356 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2357 @return std::unique_ptr holding a pointer to instance of T.
2358 */
2359template <typename T, typename Deleter = detail::Deleter<T>, typename... Args>
2360std::enable_if_t<!std::is_array<T>::value, std::unique_ptr<T, Deleter>>
2362 return std::unique_ptr<T, Deleter>(
2363 ut::new_withkey<T>(key, std::forward<Args>(args)...));
2364}
2365
2366/** Dynamically allocates storage for an object of type T. Constructs the object
2367 of type T with provided Args. Wraps the pointer to an array of T instance
2368 into the std::unique_ptr.
2369
2370 This overload participates in overload resolution only if T
2371 is an array type with unknown compile-time bound.
2372
2373 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2374 through PFS, observability for particular parts of the system which want to
2375 use it will be lost or in best case inaccurate. Please have a strong reason
2376 to do so.
2377
2378 @return std::unique_ptr holding a pointer to an array of size instances of
2379 T.
2380 */
2381template <typename T,
2382 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2383std::enable_if_t<detail::is_unbounded_array_v<T>, std::unique_ptr<T, Deleter>>
2384make_unique(size_t size) {
2385 return std::unique_ptr<T, Deleter>(
2386 ut::new_arr<std::remove_extent_t<T>>(ut::Count{size}));
2387}
2388
2389/** Dynamically allocates storage for an object of type T. Constructs the object
2390 of type T with provided Args. Wraps the pointer to an array of T instances
2391 into the std::unique_ptr with custom deleter which knows how to handle
2392 PFS-enabled dynamic memory allocations. Instruments the memory with given
2393 PSI memory key in case PFS memory support is enabled.
2394
2395 This overload participates in overload resolution only if T
2396 is an array type with unknown compile-time bound.
2397
2398 @return std::unique_ptr holding a pointer to an array of size instances of
2399 T.
2400 */
2401template <typename T,
2402 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2403std::enable_if_t<detail::is_unbounded_array_v<T>, std::unique_ptr<T, Deleter>>
2405 return std::unique_ptr<T, Deleter>(
2406 ut::new_arr_withkey<std::remove_extent_t<T>>(key, ut::Count{size}));
2407}
2408
2409/** std::unique_ptr for arrays of known compile-time bound are disallowed.
2410
2411 For more details see 4.3 paragraph from
2412 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3588.txt
2413 */
2414template <typename T, typename... Args>
2415std::enable_if_t<detail::is_bounded_array_v<T>> make_unique(Args &&...) =
2416 delete;
2417
2418/** std::unique_ptr in PFS-enabled builds for arrays of known compile-time bound
2419 are disallowed.
2420
2421 For more details see 4.3 paragraph from
2422 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3588.txt
2423 */
2424template <typename T, typename... Args>
2425std::enable_if_t<detail::is_bounded_array_v<T>> make_unique(
2426 PSI_memory_key_t key, Args &&...) = delete;
2427
2428/** The following is a common type that is returned by all the ut::make_unique
2429 (non-aligned) specializations listed above. This is effectively a if-ladder
2430 for the following list of conditions on the input type:
2431 !std::is_array<T>::value -> std::unique_ptr<T, detail::Deleter<T>>
2432 detail::is_unbounded_array_v<T> ->
2433 std::unique_ptr<T,detail::Array_deleter<std::remove_extent_t<T>>> else (or
2434 else if detail::is_bounded_array_v<T>) -> void (we do not support bounded
2435 array ut::make_unique)
2436 */
2437template <typename T>
2438using unique_ptr = std::conditional_t<
2439 !std::is_array<T>::value, std::unique_ptr<T, detail::Deleter<T>>,
2440 std::conditional_t<
2441 detail::is_unbounded_array_v<T>,
2442 std::unique_ptr<T, detail::Array_deleter<std::remove_extent_t<T>>>,
2443 void>>;
2444
2445/** Dynamically allocates storage for an object of type T at address aligned to
2446 the requested alignment. Constructs the object of type T with provided Args.
2447 Wraps the pointer to T instance into the std::unique_ptr.
2448
2449 This overload participates in overload resolution only if T
2450 is not an array type.
2451
2452 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2453 through PFS, observability for particular parts of the system which want to
2454 use it will be lost or in best case inaccurate. Please have a strong reason
2455 to do so.
2456
2457 @param[in] alignment Alignment requirement for storage to be allocated.
2458 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2459 @return std::unique_ptr holding a pointer to instance of T.
2460 */
2461template <typename T, typename Deleter = detail::Aligned_deleter<T>,
2462 typename... Args>
2463std::enable_if_t<!std::is_array<T>::value, std::unique_ptr<T, Deleter>>
2464make_unique_aligned(size_t alignment, Args &&...args) {
2465 return std::unique_ptr<T, Deleter>(
2466 ut::aligned_new<T>(alignment, std::forward<Args>(args)...));
2467}
2468
2469/** Dynamically allocates storage for an array of objects of type T at address
2470 aligned to the requested alignment. Constructs the object of type T with
2471 provided Args. Wraps the pointer to T instance into the std::unique_ptr with
2472 custom deleter which knows how to handle PFS-enabled dynamic memory
2473 allocations. Instruments the memory with given PSI memory key in case PFS
2474 memory support is enabled.
2475
2476 This overload participates in overload resolution only if T is not an array
2477 type.
2478
2479 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2480 @param[in] alignment Alignment requirement for storage to be allocated.
2481 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2482 @return std::unique_ptr holding a pointer to instance of T.
2483 */
2484template <typename T, typename Deleter = detail::Aligned_deleter<T>,
2485 typename... Args>
2486std::enable_if_t<!std::is_array<T>::value, std::unique_ptr<T, Deleter>>
2487make_unique_aligned(PSI_memory_key_t key, size_t alignment, Args &&...args) {
2488 return std::unique_ptr<T, Deleter>(
2489 ut::aligned_new_withkey<T>(key, alignment, std::forward<Args>(args)...));
2490}
2491
2492/** Dynamically allocates storage for an array of requested size of objects of
2493 type T at address aligned to the requested alignment. Constructs the object
2494 of type T with provided Args. Wraps the pointer to an array of T instance
2495 into the std::unique_ptr.
2496
2497 This overload participates in overload resolution only if T
2498 is an array type with unknown compile-time bound.
2499
2500 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2501 through PFS, observability for particular parts of the system which want to
2502 use it will be lost or in best case inaccurate. Please have a strong reason
2503 to do so.
2504
2505 @param[in] alignment Alignment requirement for storage to be allocated.
2506 @param[in] size Size of the array of objects T to allocate.
2507 @return std::unique_ptr holding a pointer to an array of size instances of
2508 T.
2509 */
2510template <typename T, typename Deleter = detail::Aligned_array_deleter<
2511 std::remove_extent_t<T>>>
2512std::enable_if_t<detail::is_unbounded_array_v<T>, std::unique_ptr<T, Deleter>>
2513make_unique_aligned(size_t alignment, size_t size) {
2514 return std::unique_ptr<T, Deleter>(
2515 ut::aligned_new_arr<std::remove_extent_t<T>>(alignment, ut::Count{size}));
2516}
2517
2518/** Dynamically allocates storage for an array of requested size of objects of
2519 type T at address aligned to the requested alignment. Constructs the object
2520 of type T with provided Args. Wraps the pointer to an array of T instances
2521 into the std::unique_ptr with custom deleter which knows how to handle
2522 PFS-enabled dynamic memory allocations. Instruments the memory with given
2523 PSI memory key in case PFS memory support is enabled.
2524
2525 This overload participates in overload resolution only if T
2526 is an array type with unknown compile-time bound.
2527
2528 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2529 @param[in] alignment Alignment requirement for storage to be allocated.
2530 @param[in] size Size of the array of objects T to allocate.
2531 @return std::unique_ptr holding a pointer to an array of size instances of
2532 T.
2533 */
2534template <typename T, typename Deleter = detail::Aligned_array_deleter<
2535 std::remove_extent_t<T>>>
2536std::enable_if_t<detail::is_unbounded_array_v<T>, std::unique_ptr<T, Deleter>>
2537make_unique_aligned(PSI_memory_key_t key, size_t alignment, size_t size) {
2538 return std::unique_ptr<T, Deleter>(
2539 ut::aligned_new_arr_withkey<std::remove_extent_t<T>>(key, alignment,
2540 ut::Count{size}));
2541}
2542
2543/** std::unique_ptr for arrays of known compile-time bound are disallowed.
2544
2545 For more details see 4.3 paragraph from
2546 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3588.txt
2547 */
2548template <typename T, typename... Args>
2549std::enable_if_t<detail::is_bounded_array_v<T>> make_unique_aligned(
2550 Args &&...) = delete;
2551
2552/** std::unique_ptr in PFS-enabled builds for arrays of known compile-time bound
2553 are disallowed.
2554
2555 For more details see 4.3 paragraph from
2556 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3588.txt
2557 */
2558template <typename T, typename... Args>
2559std::enable_if_t<detail::is_bounded_array_v<T>> make_unique_aligned(
2560 PSI_memory_key_t key, Args &&...) = delete;
2561
2562/** The following is a common type that is returned by all the
2563 ut::make_unique_aligned (non-aligned) specializations listed above. This is
2564 effectively a if-ladder for the following list of conditions on the input
2565 type: !std::is_array<T>::value -> std::unique_ptr<T,
2566 detail::Aligned_deleter<T>> detail::is_unbounded_array_v<T> ->
2567 std::unique_ptr<T,detail::Aligned_array_deleter<std::remove_extent_t<T>>>
2568 else (or else if detail::is_bounded_array_v<T>) -> void (we do not support
2569 bounded array ut::make_unique)
2570 */
2571template <typename T>
2572using unique_ptr_aligned = std::conditional_t<
2573 !std::is_array<T>::value, std::unique_ptr<T, detail::Aligned_deleter<T>>,
2574 std::conditional_t<detail::is_unbounded_array_v<T>,
2576 std::remove_extent_t<T>>>,
2577 void>>;
2578
2579/** Dynamically allocates storage for an object of type T. Constructs the object
2580 of type T with provided Args. Wraps the pointer to T instance into the
2581 std::shared_ptr.
2582
2583 This overload participates in overload resolution only if T
2584 is not an array type.
2585
2586 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2587 through PFS, observability for particular parts of the system which want to
2588 use it will be lost or in best case inaccurate. Please have a strong reason
2589 to do so.
2590
2591 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2592 @return std::shared_ptr holding a pointer to instance of T.
2593 */
2594template <typename T, typename Deleter = detail::Deleter<T>, typename... Args>
2595std::enable_if_t<!std::is_array<T>::value, std::shared_ptr<T>> make_shared(
2596 Args &&...args) {
2597 return std::shared_ptr<T>(ut::new_<T>(std::forward<Args>(args)...),
2598 Deleter{});
2599}
2600
2601/** Dynamically allocates storage for an object of type T. Constructs the object
2602 of type T with provided Args. Wraps the pointer to T instance into the
2603 std::shared_ptr with custom deleter which knows how to handle PFS-enabled
2604 dynamic memory allocations. Instruments the memory with given PSI memory key
2605 in case PFS memory support is enabled.
2606
2607 This overload participates in overload resolution only if T
2608 is not an array type.
2609
2610 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2611 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2612 @return std::shared_ptr holding a pointer to instance of T.
2613 */
2614template <typename T, typename Deleter = detail::Deleter<T>, typename... Args>
2615std::enable_if_t<!std::is_array<T>::value, std::shared_ptr<T>> make_shared(
2616 PSI_memory_key_t key, Args &&...args) {
2617 return std::shared_ptr<T>(
2618 ut::new_withkey<T>(key, std::forward<Args>(args)...), Deleter{});
2619}
2620
2621/** Dynamically allocates storage for an array of requested size of objects of
2622 type T. Constructs the object of type T with provided Args. Wraps the
2623 pointer to an array of T instance into the std::shared_ptr.
2624
2625 This overload participates in overload resolution only if T
2626 is an array type with unknown compile-time bound.
2627
2628 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2629 through PFS, observability for particular parts of the system which want to
2630 use it will be lost or in best case inaccurate. Please have a strong reason
2631 to do so.
2632
2633 @param[in] size Size of the array of objects T to allocate.
2634 @return std::shared_ptr holding a pointer to an array of size instances of
2635 T.
2636 */
2637template <typename T,
2638 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2639std::enable_if_t<detail::is_unbounded_array_v<T>, std::shared_ptr<T>>
2640make_shared(size_t size) {
2641 return std::shared_ptr<T>(
2642 ut::new_arr<std::remove_extent_t<T>>(ut::Count{size}), Deleter{});
2643}
2644
2645/** Dynamically allocates storage for an array of requested size of objects of
2646 type T. Constructs the object of type T with provided Args. Wraps the
2647 pointer to an array of T instances into the std::shared_ptr with custom
2648 deleter which knows how to handle PFS-enabled dynamic memory allocations.
2649 Instruments the memory with given PSI memory key in case PFS memory support
2650 is enabled.
2651
2652 This overload participates in overload resolution only if T
2653 is an array type with unknown compile-time bound.
2654
2655 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2656 @param[in] size Size of the array of objects T to allocate.
2657 @return std::shared_ptr holding a pointer to an array of size instances of
2658 T.
2659 */
2660template <typename T,
2661 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2662std::enable_if_t<detail::is_unbounded_array_v<T>, std::shared_ptr<T>>
2664 return std::shared_ptr<T>(
2665 ut::new_arr_withkey<std::remove_extent_t<T>>(key, ut::Count{size}),
2666 Deleter{});
2667}
2668
2669/** Dynamically allocates storage for an array of objects of type T. Constructs
2670 the object of type T with provided Args. Wraps the pointer to an array of T
2671 instance into the std::shared_ptr.
2672
2673 This overload participates in overload resolution only if T
2674 is an array type with known compile-time bound.
2675
2676 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2677 through PFS, observability for particular parts of the system which want to
2678 use it will be lost or in best case inaccurate. Please have a strong reason
2679 to do so.
2680
2681 @return std::shared_ptr holding a pointer to an array of size instances of
2682 T.
2683 */
2684template <typename T,
2685 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2686std::enable_if_t<detail::is_bounded_array_v<T>, std::shared_ptr<T>>
2688 return std::shared_ptr<T>(ut::new_arr<std::remove_extent_t<T>>(
2689 ut::Count{detail::bounded_array_size_v<T>}),
2690 Deleter{});
2691}
2692
2693/** Dynamically allocates storage for an array of objects of type T. Constructs
2694 the object of type T with provided Args. Wraps the pointer to an array of T
2695 instances into the std::shared_ptr with custom deleter which knows how to
2696 handle PFS-enabled dynamic memory allocations. Instruments the memory with
2697 given PSI memory key in case PFS memory support is enabled.
2698
2699 This overload participates in overload resolution only if T
2700 is an array type with known compile-time bound.
2701
2702 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2703 @return std::shared_ptr holding a pointer to an array of size instances of
2704 T.
2705 */
2706template <typename T,
2707 typename Deleter = detail::Array_deleter<std::remove_extent_t<T>>>
2708std::enable_if_t<detail::is_bounded_array_v<T>, std::shared_ptr<T>> make_shared(
2710 return std::shared_ptr<T>(
2711 ut::new_arr_withkey<std::remove_extent_t<T>>(
2712 key, ut::Count{detail::bounded_array_size_v<T>}),
2713 Deleter{});
2714}
2715
2716/** Dynamically allocates storage for an object of type T at address aligned to
2717 the requested alignment. Constructs the object of type T with provided Args.
2718 Wraps the pointer to T instance into the std::shared_ptr.
2719
2720 This overload participates in overload resolution only if T
2721 is not an array type.
2722
2723 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2724 through PFS, observability for particular parts of the system which want to
2725 use it will be lost or in best case inaccurate. Please have a strong reason
2726 to do so.
2727
2728 @param[in] alignment Alignment requirement for storage to be allocated.
2729 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2730 @return std::shared_ptr holding a pointer to instance of T.
2731 */
2732template <typename T, typename Deleter = detail::Aligned_deleter<T>,
2733 typename... Args>
2734std::enable_if_t<!std::is_array<T>::value, std::shared_ptr<T>>
2735make_shared_aligned(size_t alignment, Args &&...args) {
2736 return std::shared_ptr<T>(
2737 ut::aligned_new<T>(alignment, std::forward<Args>(args)...), Deleter{});
2738}
2739
2740/** Dynamically allocates storage for an object of type T at address aligned to
2741 the requested alignment. Constructs the object of type T with provided Args.
2742 Wraps the pointer to T instance into the std::shared_ptr with custom deleter
2743 which knows how to handle PFS-enabled dynamic memory allocations.
2744 Instruments the memory with given PSI memory key in case PFS memory support
2745 is enabled.
2746
2747 This overload participates in overload resolution only if T
2748 is not an array type.
2749
2750 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2751 @param[in] alignment Alignment requirement for storage to be allocated.
2752 @param[in] args Arguments one wishes to pass over to T constructor(s) .
2753 @return std::shared_ptr holding a pointer to instance of T.
2754 */
2755template <typename T, typename Deleter = detail::Aligned_deleter<T>,
2756 typename... Args>
2757std::enable_if_t<!std::is_array<T>::value, std::shared_ptr<T>>
2758make_shared_aligned(PSI_memory_key_t key, size_t alignment, Args &&...args) {
2759 return std::shared_ptr<T>(
2760 ut::aligned_new_withkey<T>(key, alignment, std::forward<Args>(args)...),
2761 Deleter{});
2762}
2763
2764/** Dynamically allocates storage for an array of requested size of objects of
2765 type T at address aligned to the requested alignment. Constructs the object
2766 of type T with provided Args. Wraps the pointer to an array of T instance
2767 into the std::shared_ptr.
2768
2769 This overload participates in overload resolution only if T
2770 is an array type with unknown compile-time bound.
2771
2772 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2773 through PFS, observability for particular parts of the system which want to
2774 use it will be lost or in best case inaccurate. Please have a strong reason
2775 to do so.
2776
2777 @param[in] alignment Alignment requirement for storage to be allocated.
2778 @param[in] size Size of the array of objects T to allocate.
2779 @return std::shared_ptr holding a pointer to an array of size instances of
2780 T.
2781 */
2782template <typename T, typename Deleter = detail::Aligned_array_deleter<
2783 std::remove_extent_t<T>>>
2784std::enable_if_t<detail::is_unbounded_array_v<T>, std::shared_ptr<T>>
2785make_shared_aligned(size_t alignment, size_t size) {
2786 return std::shared_ptr<T>(
2787 ut::aligned_new_arr<std::remove_extent_t<T>>(alignment, ut::Count{size}),
2788 Deleter{});
2789}
2790
2791/** Dynamically allocates storage for an array of requested size of objects of
2792 type T at address aligned to the requested alignment. Constructs the object
2793 of type T with provided Args. Wraps the pointer to an array of T instances
2794 into the std::shared_ptr with custom deleter which knows how to handle
2795 PFS-enabled dynamic memory allocations. Instruments the memory with given
2796 PSI memory key in case PFS memory support is enabled.
2797
2798 This overload participates in overload resolution only if T
2799 is an array type with unknown compile-time bound.
2800
2801 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2802 @param[in] alignment Alignment requirement for storage to be allocated.
2803 @param[in] size Size of the array of objects T to allocate.
2804 @return std::shared_ptr holding a pointer to an array of size instances of
2805 T.
2806 */
2807template <typename T, typename Deleter = detail::Aligned_array_deleter<
2808 std::remove_extent_t<T>>>
2809std::enable_if_t<detail::is_unbounded_array_v<T>, std::shared_ptr<T>>
2810make_shared_aligned(PSI_memory_key_t key, size_t alignment, size_t size) {
2811 return std::shared_ptr<T>(
2812 ut::aligned_new_arr_withkey<std::remove_extent_t<T>>(key, alignment,
2813 ut::Count{size}),
2814 Deleter{});
2815}
2816
2817/** Dynamically allocates storage for an array of objects of type T at address
2818 aligned to the requested alignment. Constructs the object of type T with
2819 provided Args. Wraps the pointer to an array of T instance into the
2820 std::shared_ptr.
2821
2822 This overload participates in overload resolution only if T
2823 is an array type with known compile-time bound.
2824
2825 NOTE: Given that this function will _NOT_ be instrumenting the allocation
2826 through PFS, observability for particular parts of the system which want to
2827 use it will be lost or in best case inaccurate. Please have a strong reason
2828 to do so.
2829
2830 @param[in] alignment Alignment requirement for storage to be allocated.
2831 @return std::shared_ptr holding a pointer to an array of size instances of
2832 T.
2833 */
2834template <typename T, typename Deleter = detail::Aligned_array_deleter<
2835 std::remove_extent_t<T>>>
2836std::enable_if_t<detail::is_bounded_array_v<T>, std::shared_ptr<T>>
2837make_shared_aligned(size_t alignment) {
2838 return std::shared_ptr<T>(
2839 ut::aligned_new_arr<std::remove_extent_t<T>>(
2840 alignment, ut::Count{detail::bounded_array_size_v<T>}),
2841 Deleter{});
2842}
2843
2844/** Dynamically allocates storage for an array of objects of type T at address
2845 aligned to the requested alignment. Constructs the object of type T with
2846 provided Args. Wraps the pointer to an array of T instances into the
2847 std::shared_ptr with custom deleter which knows how to handle PFS-enabled
2848 dynamic memory allocations. Instruments the memory with given PSI memory key
2849 in case PFS memory support is enabled.
2850
2851 This overload participates in overload resolution only if T
2852 is an array type with known compile-time bound.
2853
2854 @param[in] key PSI memory key to be used for PFS memory instrumentation.
2855 @param[in] alignment Alignment requirement for storage to be allocated.
2856 @return std::shared_ptr holding a pointer to an array of size instances of
2857 T.
2858 */
2859template <typename T, typename Deleter = detail::Aligned_array_deleter<
2860 std::remove_extent_t<T>>>
2861std::enable_if_t<detail::is_bounded_array_v<T>, std::shared_ptr<T>>
2863 return std::shared_ptr<T>(
2864 ut::aligned_new_arr_withkey<std::remove_extent_t<T>>(
2865 key, alignment, ut::Count{detail::bounded_array_size_v<T>}),
2866 Deleter{});
2867}
2868
2869/** Specialization of basic_ostringstream which uses ut::allocator. Please note
2870 that it's .str() method returns std::basic_string which is not std::string,
2871 so it has similar API (in particular .c_str()), but you can't assign it to
2872 regular, std::string.
2873 */
2875 std::basic_ostringstream<char, std::char_traits<char>, ut::allocator<char>>;
2876
2877/** Specialization of vector which uses allocator. */
2878template <typename T>
2879using vector = std::vector<T, ut::allocator<T>>;
2880
2881/** Specialization of list which uses ut_allocator. */
2882template <typename T>
2883using list = std::list<T, ut::allocator<T>>;
2884
2885/** Specialization of set which uses ut_allocator. */
2886template <typename Key, typename Compare = std::less<Key>>
2887using set = std::set<Key, Compare, ut::allocator<Key>>;
2888
2889template <typename Key>
2891 std::unordered_set<Key, std::hash<Key>, std::equal_to<Key>,
2893
2894/** Specialization of map which uses ut_allocator. */
2895template <typename Key, typename Value, typename Compare = std::less<Key>>
2896using map =
2897 std::map<Key, Value, Compare, ut::allocator<std::pair<const Key, Value>>>;
2898
2899template <typename Key, typename Value, typename Hash = std::hash<Key>,
2900 typename Key_equal = std::equal_to<Key>>
2902 std::unordered_map<Key, Value, Hash, Key_equal,
2904
2905} // namespace ut
2906
2907#endif /* ut0new_h */
Definition: tls_cipher.cc:37
a nullable SQL value.
Definition: sql_value.h:40
Lightweight convenience wrapper which manages a dynamically allocated array of over-aligned types.
Definition: ut0new.h:2018
void dealloc()
Invokes destructors of instances of type T, if applicable.
Definition: ut0new.h:2106
void alloc(Count count)
Allocates sufficiently large memory of dynamic storage duration to fit the array of size number of el...
Definition: ut0new.h:2040
void alloc(Args &&...args)
Allocates sufficiently large memory of dynamic storage duration to fit the array of size number of el...
Definition: ut0new.h:2058
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:2096
T * ptr
Definition: ut0new.h:2019
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:2076
~aligned_array_pointer()
Destructor.
Definition: ut0new.h:2026
Lightweight convenience wrapper which manages dynamically allocated over-aligned type.
Definition: ut0new.h:1924
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:1963
void alloc(Args &&...args)
Allocates sufficiently large memory of dynamic storage duration to fit the instance of type T at the ...
Definition: ut0new.h:1946
~aligned_pointer()
Destructor.
Definition: ut0new.h:1932
T * ptr
Definition: ut0new.h:1925
void dealloc()
Invokes the destructor of instance of type T, if applicable.
Definition: ut0new.h:1972
Allocator that allows std::* containers to manage their memory through ut::malloc* and ut::free libra...
Definition: ut0new.h:2182
T & reference
Definition: ut0new.h:2186
void deallocate(pointer ptr, size_type n_elements=0)
Releases the memory allocated through ut::allocator<T>::allocate().
Definition: ut0new.h:2282
~allocator()=default
const T * const_pointer
Definition: ut0new.h:2185
ptrdiff_t difference_type
Definition: ut0new.h:2190
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:2188
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:2219
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:2262
allocator(PSI_memory_key key)
Explicit constructor.
Definition: ut0new.h:2203
size_type max_size() const
Return the maximum number of objects that can be allocated by this allocator.
Definition: ut0new.h:2245
const T & const_reference
Definition: ut0new.h:2187
allocator(allocator< T, Allocator_base > &&)=default
allocator()
Default constructor, use mem_key_std.
Definition: ut0new.h:2198
bool operator!=(const ut::allocator< T, Allocator_base > &other) const
Non-equality of allocators instantiated with same types T.
Definition: ut0new.h:2237
allocator(const allocator< T, Allocator_base > &)=default
size_t size_type
Definition: ut0new.h:2189
bool operator==(const ut::allocator< T, Allocator_base > &) const
Equality of allocators instantiated with same types T.
Definition: ut0new.h:2233
T * pointer
Definition: ut0new.h:2184
Implementation bits and pieces of include/ut0new.h.
unsigned int PSI_memory_key
Instrumented memory key.
Definition: psi_memory_bits.h:49
#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:56
static int count
Definition: myisam_ftdump.cc:43
Instrumentation helpers for memory allocation.
std::atomic< Type > N
Definition: ut0counter.h:225
Definition: fts0fts.cc:236
Definition: os0file.h:86
std::string_view Key
The key type for the hash structure in HashJoinRowBuffer.
Definition: hash_join_buffer.h:102
Definition: authentication.cc:36
Alignment
Enum class describing alignment-requirements.
Definition: lock_free_type.h:75
constexpr bool is_unbounded_array_v< T[]>
Definition: ut0new.h:2291
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:2301
constexpr bool is_bounded_array_v
Definition: ut0new.h:2294
constexpr bool is_unbounded_array_v
Definition: ut0new.h:2289
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:2299
constexpr bool is_bounded_array_v< T[N]>
Definition: ut0new.h:2296
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:1527
std::unordered_map< Key, Value, Hash, Key_equal, ut::allocator< std::pair< const Key, Value > > > unordered_map
Definition: ut0new.h:2903
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:1126
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:1595
void * zalloc_withkey(PSI_memory_key_t key, std::size_t size) noexcept
Dynamically allocates zero-initialized storage of given size.
Definition: ut0new.h:633
void * malloc_withkey(PSI_memory_key_t key, std::size_t size) noexcept
Dynamically allocates storage of given size.
Definition: ut0new.h:597
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:1550
void * malloc_large_page(std::size_t size) noexcept
Dynamically allocates memory backed up by large (huge) pages.
Definition: ut0new.h:1272
std::unordered_set< Key, std::hash< Key >, std::equal_to< Key >, ut::allocator< Key > > unordered_set
Definition: ut0new.h:2892
std::basic_ostringstream< char, std::char_traits< char >, ut::allocator< char > > ostringstream
Specialization of basic_ostringstream which uses ut::allocator.
Definition: ut0new.h:2875
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:1210
std::vector< T, ut::allocator< T > > vector
Specialization of vector which uses allocator.
Definition: ut0new.h:2879
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:1896
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:2342
void delete_(T *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::new*() variants.
Definition: ut0new.h:810
std::set< Key, Compare, ut::allocator< Key > > set
Specialization of set which uses ut_allocator.
Definition: ut0new.h:2887
void * malloc_page(std::size_t size) noexcept
Dynamically allocates system page-aligned storage of given size.
Definition: ut0new.h:1176
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:676
void delete_arr(T *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::new_arr*() variants.
Definition: ut0new.h:1110
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:2464
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:1716
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:1308
bool free_page(void *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::malloc_page*() variants.
Definition: ut0new.h:1226
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:1248
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:1294
std::map< Key, Value, Compare, ut::allocator< std::pair< const Key, Value > > > map
Specialization of map which uses ut_allocator.
Definition: ut0new.h:2897
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:2735
void * malloc(std::size_t size) noexcept
Dynamically allocates storage of given size.
Definition: ut0new.h:618
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:2443
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:1839
T * new_(Args &&...args)
Dynamically allocates storage for an object of type T.
Definition: ut0new.h:795
std::list< T, ut::allocator< T > > list
Specialization of list which uses ut_allocator.
Definition: ut0new.h:2883
void free(void *ptr) noexcept
Releases storage which has been dynamically allocated through any of the ut::malloc*(),...
Definition: ut0new.h:718
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:1485
constexpr bool WITH_PFS_MEMORY
Definition: ut0new.h:581
void aligned_delete(T *ptr) noexcept
Releases storage which has been dynamically allocated through any of the aligned_new_*() variants.
Definition: ut0new.h:1651
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:1149
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:2577
void * realloc(void *ptr, std::size_t size) noexcept
Upsizes or downsizes already dynamically allocated storage to the new size.
Definition: ut0new.h:704
T * new_arr_withkey(PSI_memory_key_t key, Args &&...args)
Dynamically allocates storage for an array of T's.
Definition: ut0new.h:875
T * new_withkey(PSI_memory_key_t key, Args &&...args)
Dynamically allocates storage for an object of type T.
Definition: ut0new.h:752
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:1196
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:1325
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:2595
void aligned_free(void *ptr) noexcept
Releases storage which has been dynamically allocated through any of the aligned_alloc_*() or aligned...
Definition: ut0new.h:1564
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:1508
T * new_arr(Args &&...args)
Dynamically allocates storage for an array of T's.
Definition: ut0new.h:960
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:1636
void * zalloc(std::size_t size) noexcept
Dynamically allocates zero-initialized storage of given size.
Definition: ut0new.h:654
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:99
Memory instrument information.
Definition: psi_memory_bits.h:58
Definition: ut0new.h:558
static constexpr int value
Definition: ut0new.h:559
Light-weight and type-safe wrapper which serves a purpose of being able to select proper ut::new_arr*...
Definition: ut0new.h:982
Count(size_t count)
Definition: ut0new.h:983
size_t m_count
Definition: ut0new.h:985
size_t operator()() const
Definition: ut0new.h:984
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:2228
Small wrapper which utilizes SFINAE to dispatch the call to appropriate aligned allocator implementat...
Definition: aligned_alloc.h:697
Definition: ut0new.h:2319
void operator()(T *ptr)
Definition: ut0new.h:2320
Definition: ut0new.h:2314
void operator()(T *ptr)
Definition: ut0new.h:2315
Small wrapper which utilizes SFINAE to dispatch the call to appropriate allocator implementation.
Definition: alloc.h:435
Definition: ut0new.h:2309
void operator()(T *ptr)
Definition: ut0new.h:2310
Definition: ut0new.h:2304
void operator()(T *ptr)
Definition: ut0new.h:2305
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:2132
void * allocate_impl(size_t n_bytes)
Definition: ut0new.h:2141
const PSI_memory_key m_key
Definition: ut0new.h:2146
PSI_memory_key get_mem_key() const
Definition: ut0new.h:2139
allocator_base_pfs(PSI_memory_key key)
Definition: ut0new.h:2133
allocator_base_pfs(const allocator_base_pfs< U > &other)
Definition: ut0new.h:2136
Definition: ut0new.h:2122
void * allocate_impl(size_t n_bytes)
Definition: ut0new.h:2128
allocator_base(const allocator_base< U > &other)
Definition: ut0new.h:2126
allocator_base(PSI_memory_key)
Definition: ut0new.h:2123
Definition: ut0new.h:1332
Version control for database, common definitions, and include files.
#define UT_ARR_SIZE(a)
Definition: univ.i:524
Utilities for byte operations.
Utilities related to CPU cache.
Debug utilities for Innobase.
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:69
#define ut_a(EXPR)
Abort execution if EXPR does not evaluate to nonzero.
Definition: ut0dbg.h:57
PSI_memory_key mem_key_ddl
Definition: ut0new.cc:61
void ut_new_boot_safe()
Setup the internal objects needed for ut::*_withkey() to operate.
Definition: ut0new.cc:139
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:58
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:537
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)
gcc 5 fails to evaluate costexprs at compile time.
Definition: ut0new.h:511
PSI_memory_key mem_key_lock_sys
Definition: ut0new.cc:57
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:550
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:120
PSI_memory_key mem_key_partitioning
Definition: ut0new.cc:59
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:247
PSI_memory_key mem_key_std
Definition: ut0new.cc:62
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:60
PSI_memory_key mem_key_trx_sys_t_rw_trx_ids
Definition: ut0new.cc:63
static constexpr size_t n_auto
Definition: ut0new.h:448
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:524
PSI_memory_key mem_key_undo_spaces
Definition: ut0new.cc:64
PSI_memory_key mem_key_ut_lock_free_hash_t
Definition: ut0new.cc:65
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:42