AllocPolicy.h 4.5 KB

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