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