1 /** 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <cstdlib> 20 #include <memory> 21 #include <type_traits> 22 23 namespace android { 24 namespace uirenderer { 25 26 /** Manages an array of T elements, freeing the array in the destructor. 27 * Does NOT call any constructors/destructors on T (T must be POD). 28 */ 29 template <typename T, 30 typename = std::enable_if_t<std::is_trivially_default_constructible<T>::value && 31 std::is_trivially_destructible<T>::value>> 32 class AutoTMalloc { 33 public: 34 /** Takes ownership of the ptr. The ptr must be a value which can be passed to std::free. */ fPtr(ptr)35 explicit AutoTMalloc(T* ptr = nullptr) : fPtr(ptr) {} 36 37 /** Allocates space for 'count' Ts. */ AutoTMalloc(size_t count)38 explicit AutoTMalloc(size_t count) : fPtr(mallocIfCountThrowOnFail(count)) {} 39 40 AutoTMalloc(AutoTMalloc&&) = default; 41 AutoTMalloc& operator=(AutoTMalloc&&) = default; 42 43 /** Resize the memory area pointed to by the current ptr preserving contents. */ realloc(size_t count)44 void realloc(size_t count) { fPtr.reset(reallocIfCountThrowOnFail(count)); } 45 46 /** Resize the memory area pointed to by the current ptr without preserving contents. */ 47 T* reset(size_t count = 0) { 48 fPtr.reset(mallocIfCountThrowOnFail(count)); 49 return this->get(); 50 } 51 get()52 T* get() const { return fPtr.get(); } 53 54 operator T*() { return fPtr.get(); } 55 56 operator const T*() const { return fPtr.get(); } 57 58 T& operator[](int index) { return fPtr.get()[index]; } 59 60 const T& operator[](int index) const { return fPtr.get()[index]; } 61 62 /** 63 * Transfer ownership of the ptr to the caller, setting the internal 64 * pointer to NULL. Note that this differs from get(), which also returns 65 * the pointer, but it does not transfer ownership. 66 */ release()67 T* release() { return fPtr.release(); } 68 69 private: 70 struct FreeDeleter { operatorFreeDeleter71 void operator()(uint8_t* p) { std::free(p); } 72 }; 73 std::unique_ptr<T, FreeDeleter> fPtr; 74 mallocIfCountThrowOnFail(size_t count)75 T* mallocIfCountThrowOnFail(size_t count) { 76 T* newPtr = nullptr; 77 if (count) { 78 newPtr = (T*)std::malloc(count * sizeof(T)); 79 LOG_ALWAYS_FATAL_IF(!newPtr, "failed to malloc %zu bytes", count * sizeof(T)); 80 } 81 return newPtr; 82 } reallocIfCountThrowOnFail(size_t count)83 T* reallocIfCountThrowOnFail(size_t count) { 84 T* newPtr = nullptr; 85 if (count) { 86 newPtr = (T*)std::realloc(fPtr.release(), count * sizeof(T)); 87 LOG_ALWAYS_FATAL_IF(!newPtr, "failed to realloc %zu bytes", count * sizeof(T)); 88 } 89 return newPtr; 90 } 91 }; 92 93 } // namespace uirenderer 94 } // namespace android 95