Bug 1852740: add tests for the `fetchpriority` attribute in Link headers. r=necko...
[gecko.git] / mfbt / AllocPolicy.h
blobe5c62bcd640c5f97350254ba5e644772ded5bd6b
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /*
8 * An allocation policy concept, usable for structures and algorithms to
9 * control how memory is allocated and how failures are handled.
12 #ifndef mozilla_AllocPolicy_h
13 #define mozilla_AllocPolicy_h
15 #include "mozilla/Attributes.h"
16 #include "mozilla/Assertions.h"
17 #include "mozilla/TemplateLib.h"
19 #include <stddef.h>
20 #include <stdlib.h>
22 namespace mozilla {
25 * Allocation policies are used to implement the standard allocation behaviors
26 * in a customizable way. Additionally, custom behaviors may be added to these
27 * behaviors, such as additionally reporting an error through an out-of-band
28 * mechanism when OOM occurs. The concept modeled here is as follows:
30 * - public copy constructor, assignment, destructor
31 * - template <typename T> T* maybe_pod_malloc(size_t)
32 * Fallible, but doesn't report an error on OOM.
33 * - template <typename T> T* maybe_pod_calloc(size_t)
34 * Fallible, but doesn't report an error on OOM.
35 * - template <typename T> T* maybe_pod_realloc(T*, size_t, size_t)
36 * Fallible, but doesn't report an error on OOM. The old allocation
37 * size is passed in, in addition to the new allocation size requested.
38 * - template <typename T> T* pod_malloc(size_t)
39 * Responsible for OOM reporting when null is returned.
40 * - template <typename T> T* pod_calloc(size_t)
41 * Responsible for OOM reporting when null is returned.
42 * - template <typename T> T* pod_realloc(T*, size_t, size_t)
43 * Responsible for OOM reporting when null is returned. The old allocation
44 * size is passed in, in addition to the new allocation size requested.
45 * - template <typename T> void free_(T*, size_t)
46 * The capacity passed in must match the old allocation size.
47 * - template <typename T> void free_(T*)
48 * Frees a buffer without knowing its allocated size. This might not be
49 * implemented by allocation policies that need the allocation size.
50 * - void reportAllocOverflow() const
51 * Called on allocation overflow (that is, an allocation implicitly tried
52 * to allocate more than the available memory space -- think allocating an
53 * array of large-size objects, where N * size overflows) before null is
54 * returned.
55 * - bool checkSimulatedOOM() const
56 * Some clients generally allocate memory yet in some circumstances won't
57 * need to do so. For example, appending to a vector with a small amount of
58 * inline storage generally allocates memory, but no allocation occurs
59 * unless appending exceeds inline storage. But for testing purposes, it
60 * can be useful to treat *every* operation as allocating.
61 * Clients (such as this hypothetical append method implementation) should
62 * call this method in situations that don't allocate, but could generally,
63 * to support this. The default behavior should return true; more
64 * complicated behavior might be to return false only after a certain
65 * number of allocations-or-check-simulated-OOMs (coordinating with the
66 * other AllocPolicy methods) have occurred.
68 * mfbt provides (and typically uses by default) only MallocAllocPolicy, which
69 * does nothing more than delegate to the malloc/alloc/free functions.
73 * A policy that straightforwardly uses malloc/calloc/realloc/free and adds no
74 * extra behaviors.
76 class MallocAllocPolicy {
77 public:
78 template <typename T>
79 T* maybe_pod_malloc(size_t aNumElems) {
80 if (aNumElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
81 return nullptr;
83 return static_cast<T*>(malloc(aNumElems * sizeof(T)));
86 template <typename T>
87 T* maybe_pod_calloc(size_t aNumElems) {
88 return static_cast<T*>(calloc(aNumElems, sizeof(T)));
91 template <typename T>
92 T* maybe_pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize) {
93 if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
94 return nullptr;
96 return static_cast<T*>(realloc(aPtr, aNewSize * sizeof(T)));
99 template <typename T>
100 T* pod_malloc(size_t aNumElems) {
101 return maybe_pod_malloc<T>(aNumElems);
104 template <typename T>
105 T* pod_calloc(size_t aNumElems) {
106 return maybe_pod_calloc<T>(aNumElems);
109 template <typename T>
110 T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize) {
111 return maybe_pod_realloc<T>(aPtr, aOldSize, aNewSize);
114 template <typename T>
115 void free_(T* aPtr, size_t aNumElems = 0) {
116 free(aPtr);
119 void reportAllocOverflow() const {}
121 [[nodiscard]] bool checkSimulatedOOM() const { return true; }
125 * A policy which always fails to allocate memory, returning nullptr. Methods
126 * which expect an existing allocation assert.
128 * This type should be used in situations where you want to use a MFBT type with
129 * inline storage, and don't want to allow it to allocate on the heap.
131 class NeverAllocPolicy {
132 public:
133 template <typename T>
134 T* maybe_pod_malloc(size_t aNumElems) {
135 return nullptr;
138 template <typename T>
139 T* maybe_pod_calloc(size_t aNumElems) {
140 return nullptr;
143 template <typename T>
144 T* maybe_pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize) {
145 MOZ_CRASH("NeverAllocPolicy::maybe_pod_realloc");
148 template <typename T>
149 T* pod_malloc(size_t aNumElems) {
150 return nullptr;
153 template <typename T>
154 T* pod_calloc(size_t aNumElems) {
155 return nullptr;
158 template <typename T>
159 T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize) {
160 MOZ_CRASH("NeverAllocPolicy::pod_realloc");
163 template <typename T>
164 void free_(T* aPtr, size_t aNumElems = 0) {
165 MOZ_CRASH("NeverAllocPolicy::free_");
168 void reportAllocOverflow() const {}
170 [[nodiscard]] bool checkSimulatedOOM() const { return true; }
173 } // namespace mozilla
175 #endif /* mozilla_AllocPolicy_h */