1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "common/rs_common_def.h"
17
18 #include <mutex>
19 #include <vector>
20
21 namespace OHOS {
22 namespace Rosen {
23 namespace {
24 class MemAllocater final {
25 struct BlockHead {
26 int size;
27 char ptr[0];
28 };
29 using Cache = std::vector<char*>;
30
31 public:
32 static MemAllocater& GetInstance();
33 MemAllocater() = default;
34 ~MemAllocater();
35
36 void* Alloc(size_t size);
37 void Free(void* ptr);
38
39 private:
40 MemAllocater(const MemAllocater&) = delete;
41 MemAllocater& operator=(const MemAllocater&) = delete;
42
43 std::mutex mutex_;
44 std::unordered_map<size_t, Cache> memCaches_;
45 std::vector<char*> blocks_;
46 static constexpr unsigned sizeStep_ = 64;
47 };
48 static MemAllocater allocater;
49 }
50
GetInstance()51 MemAllocater& MemAllocater::GetInstance()
52 {
53 return allocater;
54 }
55
~MemAllocater()56 MemAllocater::~MemAllocater()
57 {
58 for (void* ptr : blocks_) {
59 if (ptr != nullptr) {
60 free(ptr);
61 }
62 }
63 blocks_.clear();
64 memCaches_.clear();
65 }
66
Alloc(size_t size)67 void* MemAllocater::Alloc(size_t size)
68 {
69 std::lock_guard<std::mutex> lock(mutex_);
70 Cache* cachePtr = nullptr;
71 auto itr = memCaches_.find(size);
72 if (itr == memCaches_.end()) {
73 Cache tempCache;
74 memCaches_.insert(std::pair<size_t, Cache>(size, tempCache));
75 itr = memCaches_.find(size);
76 cachePtr = &(itr->second);
77 cachePtr->reserve(sizeStep_);
78 } else {
79 cachePtr = &(itr->second);
80 }
81
82 if (cachePtr == nullptr) {
83 return nullptr;
84 }
85 size_t memSize = (size + sizeof(BlockHead));
86 if (cachePtr->empty()) {
87 char* block = static_cast<char*>(malloc(memSize * sizeStep_));
88 if (block == nullptr) {
89 return nullptr;
90 }
91 blocks_.push_back(block);
92 for (unsigned i = 0; i < sizeStep_; ++i) {
93 cachePtr->push_back(block + (i * memSize));
94 }
95 }
96
97 char* mem = cachePtr->back();
98 cachePtr->pop_back();
99 BlockHead* head = reinterpret_cast<BlockHead*>(mem);
100 head->size = static_cast<int>(size);
101 return head->ptr;
102 }
103
Free(void * ptr)104 void MemAllocater::Free(void* ptr)
105 {
106 if (ptr == nullptr) {
107 return;
108 }
109 std::lock_guard<std::mutex> lock(mutex_);
110 char* p = static_cast<char*>(ptr) - sizeof(BlockHead);
111 BlockHead* head = reinterpret_cast<BlockHead*>(p);
112 auto itr = memCaches_.find(head->size);
113 if (itr == memCaches_.end()) {
114 free(p);
115 } else {
116 itr->second.push_back(p);
117 }
118 }
119
operator new(size_t size)120 void* MemObject::operator new(size_t size)
121 {
122 return MemAllocater::GetInstance().Alloc(size);
123 }
124
operator delete(void * ptr)125 void MemObject::operator delete(void* ptr)
126 {
127 return MemAllocater::GetInstance().Free(ptr);
128 }
129
operator new(size_t size,const std::nothrow_t &)130 void* MemObject::operator new(size_t size, const std::nothrow_t&) noexcept
131 {
132 return MemAllocater::GetInstance().Alloc(size);
133 }
134
operator delete(void * ptr,const std::nothrow_t &)135 void MemObject::operator delete(void* ptr, const std::nothrow_t&) noexcept
136 {
137 return MemAllocater::GetInstance().Free(ptr);
138 }
139 } // namespace Rosen
140 } // namespace OHOS
141