AllocPolicy.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /*
  6. * An allocation policy concept, usable for structures and algorithms to
  7. * control how memory is allocated and how failures are handled.
  8. */
  9. #ifndef mozilla_AllocPolicy_h
  10. #define mozilla_AllocPolicy_h
  11. #include "mozilla/Attributes.h"
  12. #include "mozilla/TemplateLib.h"
  13. #include <stddef.h>
  14. #include <stdlib.h>
  15. namespace mozilla {
  16. /*
  17. * Allocation policies are used to implement the standard allocation behaviors
  18. * in a customizable way. Additionally, custom behaviors may be added to these
  19. * behaviors, such as additionally reporting an error through an out-of-band
  20. * mechanism when OOM occurs. The concept modeled here is as follows:
  21. *
  22. * - public copy constructor, assignment, destructor
  23. * - template <typename T> T* maybe_pod_malloc(size_t)
  24. * Fallible, but doesn't report an error on OOM.
  25. * - template <typename T> T* maybe_pod_calloc(size_t)
  26. * Fallible, but doesn't report an error on OOM.
  27. * - template <typename T> T* maybe_pod_realloc(T*, size_t, size_t)
  28. * Fallible, but doesn't report an error on OOM. The old allocation
  29. * size is passed in, in addition to the new allocation size requested.
  30. * - template <typename T> T* pod_malloc(size_t)
  31. * Responsible for OOM reporting when null is returned.
  32. * - template <typename T> T* pod_calloc(size_t)
  33. * Responsible for OOM reporting when null is returned.
  34. * - template <typename T> T* pod_realloc(T*, size_t, size_t)
  35. * Responsible for OOM reporting when null is returned. The old allocation
  36. * size is passed in, in addition to the new allocation size requested.
  37. * - void free_(void*)
  38. * - void reportAllocOverflow() const
  39. * Called on allocation overflow (that is, an allocation implicitly tried
  40. * to allocate more than the available memory space -- think allocating an
  41. * array of large-size objects, where N * size overflows) before null is
  42. * returned.
  43. * - bool checkSimulatedOOM() const
  44. * Some clients generally allocate memory yet in some circumstances won't
  45. * need to do so. For example, appending to a vector with a small amount of
  46. * inline storage generally allocates memory, but no allocation occurs
  47. * unless appending exceeds inline storage. But for testing purposes, it
  48. * can be useful to treat *every* operation as allocating.
  49. * Clients (such as this hypothetical append method implementation) should
  50. * call this method in situations that don't allocate, but could generally,
  51. * to support this. The default behavior should return true; more
  52. * complicated behavior might be to return false only after a certain
  53. * number of allocations-or-check-simulated-OOMs (coordinating with the
  54. * other AllocPolicy methods) have occurred.
  55. *
  56. * mfbt provides (and typically uses by default) only MallocAllocPolicy, which
  57. * does nothing more than delegate to the malloc/alloc/free functions.
  58. */
  59. /*
  60. * A policy that straightforwardly uses malloc/calloc/realloc/free and adds no
  61. * extra behaviors.
  62. */
  63. class MallocAllocPolicy
  64. {
  65. public:
  66. template <typename T>
  67. T* maybe_pod_malloc(size_t aNumElems)
  68. {
  69. if (aNumElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
  70. return nullptr;
  71. }
  72. return static_cast<T*>(malloc(aNumElems * sizeof(T)));
  73. }
  74. template <typename T>
  75. T* maybe_pod_calloc(size_t aNumElems)
  76. {
  77. return static_cast<T*>(calloc(aNumElems, sizeof(T)));
  78. }
  79. template <typename T>
  80. T* maybe_pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
  81. {
  82. if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
  83. return nullptr;
  84. }
  85. return static_cast<T*>(realloc(aPtr, aNewSize * sizeof(T)));
  86. }
  87. template <typename T>
  88. T* pod_malloc(size_t aNumElems)
  89. {
  90. return maybe_pod_malloc<T>(aNumElems);
  91. }
  92. template <typename T>
  93. T* pod_calloc(size_t aNumElems)
  94. {
  95. return maybe_pod_calloc<T>(aNumElems);
  96. }
  97. template <typename T>
  98. T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
  99. {
  100. return maybe_pod_realloc<T>(aPtr, aOldSize, aNewSize);
  101. }
  102. void free_(void* aPtr)
  103. {
  104. free(aPtr);
  105. }
  106. void reportAllocOverflow() const
  107. {
  108. }
  109. MOZ_MUST_USE bool checkSimulatedOOM() const
  110. {
  111. return true;
  112. }
  113. };
  114. } // namespace mozilla
  115. #endif /* mozilla_AllocPolicy_h */