tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

memory_manager_internal.h (6126B)


      1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style
      4 // license that can be found in the LICENSE file.
      5 
      6 #ifndef LIB_JXL_MEMORY_MANAGER_INTERNAL_H_
      7 #define LIB_JXL_MEMORY_MANAGER_INTERNAL_H_
      8 
      9 // Memory allocator with support for alignment + misalignment.
     10 
     11 #include <jxl/memory_manager.h>
     12 
     13 #include <cstddef>
     14 #include <memory>
     15 #include <utility>
     16 
     17 #include "lib/jxl/base/compiler_specific.h"
     18 #include "lib/jxl/base/status.h"
     19 
     20 namespace jxl {
     21 
     22 namespace memory_manager_internal {
     23 
     24 // To avoid RFOs, match L2 fill size (pairs of lines); 2 x cache line size.
     25 static constexpr size_t kAlignment = 2 * 64;
     26 static_assert((kAlignment & (kAlignment - 1)) == 0,
     27              "kAlignment must be a power of 2");
     28 
     29 // Minimum multiple for which cache set conflicts and/or loads blocked by
     30 // preceding stores can occur.
     31 static constexpr size_t kNumAlignmentGroups = 16;
     32 static constexpr size_t kAlias = kNumAlignmentGroups * kAlignment;
     33 static_assert((kNumAlignmentGroups & (kNumAlignmentGroups - 1)) == 0,
     34              "kNumAlignmentGroups must be a power of 2");
     35 
     36 }  // namespace memory_manager_internal
     37 
     38 // Initializes the memory manager instance with the passed one. The
     39 // MemoryManager passed in |memory_manager| may be NULL or contain NULL
     40 // functions which will be initialized with the default ones. If either alloc
     41 // or free are NULL, then both must be NULL, otherwise this function returns an
     42 // error.
     43 Status MemoryManagerInit(JxlMemoryManager* self,
     44                         const JxlMemoryManager* memory_manager);
     45 
     46 void* MemoryManagerAlloc(const JxlMemoryManager* memory_manager, size_t size);
     47 void MemoryManagerFree(const JxlMemoryManager* memory_manager, void* address);
     48 
     49 // Helper class to be used as a deleter in a unique_ptr<T> call.
     50 class MemoryManagerDeleteHelper {
     51 public:
     52  explicit MemoryManagerDeleteHelper(const JxlMemoryManager* memory_manager)
     53      : memory_manager_(memory_manager) {}
     54 
     55  // Delete and free the passed pointer using the memory_manager.
     56  template <typename T>
     57  void operator()(T* address) const {
     58    if (!address) {
     59      return;
     60    }
     61    address->~T();
     62    return memory_manager_->free(memory_manager_->opaque, address);
     63  }
     64 
     65 private:
     66  const JxlMemoryManager* memory_manager_;
     67 };
     68 
     69 template <typename T>
     70 using MemoryManagerUniquePtr = std::unique_ptr<T, MemoryManagerDeleteHelper>;
     71 
     72 // Creates a new object T allocating it with the memory allocator into a
     73 // unique_ptr.
     74 template <typename T, typename... Args>
     75 JXL_INLINE MemoryManagerUniquePtr<T> MemoryManagerMakeUnique(
     76    const JxlMemoryManager* memory_manager, Args&&... args) {
     77  T* mem =
     78      static_cast<T*>(memory_manager->alloc(memory_manager->opaque, sizeof(T)));
     79  if (!mem) {
     80    // Allocation error case.
     81    return MemoryManagerUniquePtr<T>(nullptr,
     82                                     MemoryManagerDeleteHelper(memory_manager));
     83  }
     84  return MemoryManagerUniquePtr<T>(new (mem) T(std::forward<Args>(args)...),
     85                                   MemoryManagerDeleteHelper(memory_manager));
     86 }
     87 
     88 // Returns recommended distance in bytes between the start of two consecutive
     89 // rows.
     90 size_t BytesPerRow(size_t xsize, size_t sizeof_t);
     91 
     92 class AlignedMemory {
     93 public:
     94  AlignedMemory()
     95      : allocation_(nullptr), memory_manager_(nullptr), address_(nullptr) {}
     96 
     97  // Copy disallowed.
     98  AlignedMemory(const AlignedMemory& other) = delete;
     99  AlignedMemory& operator=(const AlignedMemory& other) = delete;
    100 
    101  // Custom move.
    102  AlignedMemory(AlignedMemory&& other) noexcept;
    103  AlignedMemory& operator=(AlignedMemory&& other) noexcept;
    104 
    105  ~AlignedMemory();
    106 
    107  static StatusOr<AlignedMemory> Create(JxlMemoryManager* memory_manager,
    108                                        size_t size, size_t pre_padding = 0);
    109 
    110  explicit operator bool() const noexcept { return (address_ != nullptr); }
    111 
    112  template <typename T>
    113  T* address() const {
    114    return reinterpret_cast<T*>(address_);
    115  }
    116  JxlMemoryManager* memory_manager() const { return memory_manager_; }
    117 
    118  // TODO(eustas): we can offer "actually accessible" size; it is 0-2KiB bigger
    119  //               than requested size, due to generous alignment;
    120  //               might be useful for resizeable containers (e.g. PaddedBytes)
    121 
    122 private:
    123  AlignedMemory(JxlMemoryManager* memory_manager, void* allocation,
    124                size_t pre_padding);
    125 
    126  void* allocation_;
    127  JxlMemoryManager* memory_manager_;
    128  void* address_;
    129 };
    130 
    131 template <typename T>
    132 class AlignedArray {
    133 public:
    134  AlignedArray() : size_(0) {}
    135 
    136  static StatusOr<AlignedArray> Create(JxlMemoryManager* memory_manager,
    137                                       size_t size) {
    138    size_t storage_size = size * sizeof(T);
    139    JXL_ASSIGN_OR_RETURN(AlignedMemory storage,
    140                         AlignedMemory::Create(memory_manager, storage_size));
    141    T* items = storage.address<T>();
    142    for (size_t i = 0; i < size; ++i) {
    143      new (items + i) T();
    144    }
    145    return AlignedArray<T>(std::move(storage), size);
    146  }
    147 
    148  // Copy disallowed.
    149  AlignedArray(const AlignedArray& other) = delete;
    150  AlignedArray& operator=(const AlignedArray& other) = delete;
    151 
    152  // Custom move.
    153  AlignedArray(AlignedArray&& other) noexcept {
    154    size_ = other.size_;
    155    storage_ = std::move(other.storage_);
    156    other.size_ = 0;
    157  }
    158 
    159  AlignedArray& operator=(AlignedArray&& other) noexcept {
    160    if (this == &other) return *this;
    161    size_ = other.size_;
    162    storage_ = std::move(other.storage_);
    163    other.size_ = 0;
    164    return *this;
    165  }
    166 
    167  ~AlignedArray() {
    168    if (!size_) return;
    169    T* items = storage_.address<T>();
    170    for (size_t i = 0; i < size_; ++i) {
    171      items[i].~T();
    172    }
    173  }
    174 
    175  T& operator[](const size_t i) {
    176    JXL_DASSERT(i < size_);
    177    return *(storage_.address<T>() + i);
    178  }
    179  const T& operator[](const size_t i) const {
    180    JXL_DASSERT(i < size_);
    181    return *(storage_.address<T>() + i);
    182  }
    183 
    184 private:
    185  explicit AlignedArray(AlignedMemory&& storage, size_t size)
    186      : size_(size), storage_(std::move(storage)) {}
    187  size_t size_;
    188  AlignedMemory storage_;
    189 };
    190 
    191 }  // namespace jxl
    192 
    193 #endif  // LIB_JXL_MEMORY_MANAGER_INTERNAL_H_