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