• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 #ifndef CHRE_UTIL_SYNCHRONIZED_EXPANDABLE_MEMORY_POOL_IMPL_H_
18 #define CHRE_UTIL_SYNCHRONIZED_EXPANDABLE_MEMORY_POOL_IMPL_H_
19 
20 #include "chre/util/lock_guard.h"
21 #include "chre/util/memory_pool.h"
22 #include "chre/util/synchronized_expandable_memory_pool.h"
23 
24 namespace chre {
25 
26 template <typename ElementType, size_t kMemoryPoolSize,
27           size_t kMaxMemoryPoolCount>
28 SynchronizedExpandableMemoryPool<ElementType, kMemoryPoolSize,
29                                  kMaxMemoryPoolCount>::
SynchronizedExpandableMemoryPool(size_t staticBlockCount)30     SynchronizedExpandableMemoryPool(size_t staticBlockCount)
31     : kStaticBlockCount(staticBlockCount) {
32   CHRE_ASSERT(staticBlockCount > 0);
33   CHRE_ASSERT(kMaxMemoryPoolCount >= staticBlockCount);
34   for (uint8_t i = 0; i < kStaticBlockCount; i++) {
35     pushOneBlock();
36   }
37 }
38 
39 template <typename ElementType, size_t kMemoryPoolSize,
40           size_t kMaxMemoryPoolCount>
41 template <typename... Args>
42 ElementType *SynchronizedExpandableMemoryPool<
43     ElementType, kMemoryPoolSize,
allocate(Args &&...args)44     kMaxMemoryPoolCount>::allocate(Args &&...args) {
45   LockGuard<Mutex> lock(mMutex);
46   ElementType *result = nullptr;
47 
48   // TODO(b/259286151): Optimizing using pointer to a non-full block
49   for (UniquePtr<Block> &memoryPool : mMemoryPoolPtrs) {
50     result = memoryPool->allocate(args...);
51     if (result != nullptr) {
52       break;
53     }
54   }
55 
56   if (result == nullptr && pushOneBlock()) {
57     result = mMemoryPoolPtrs.back()->allocate(args...);
58   }
59 
60   if (result != nullptr) {
61     ++mSize;
62   }
63 
64   return result;
65 }
66 
67 template <typename ElementType, size_t kMemoryPoolSize,
68           size_t kMaxMemoryPoolCount>
69 void SynchronizedExpandableMemoryPool<
70     ElementType, kMemoryPoolSize,
deallocate(ElementType * element)71     kMaxMemoryPoolCount>::deallocate(ElementType *element) {
72   bool success = false;
73   LockGuard<Mutex> lock(mMutex);
74   for (UniquePtr<Block> &memoryPool : mMemoryPoolPtrs) {
75     if (memoryPool->containsAddress(element)) {
76       success = true;
77       memoryPool->deallocate(element);
78       break;
79     }
80   }
81   if (!success) {
82     CHRE_ASSERT(false);
83   } else {
84     --mSize;
85     while (
86         mMemoryPoolPtrs.size() > std::max(kStaticBlockCount, size_t(1)) &&
87         mMemoryPoolPtrs.back()->empty() &&
88         !isHalfFullBlock(mMemoryPoolPtrs[mMemoryPoolPtrs.size() - 2].get())) {
89       mMemoryPoolPtrs.pop_back();
90     }
91   }
92 }
93 
94 template <typename ElementType, size_t kMemoryPoolSize,
95           size_t kMaxMemoryPoolCount>
96 size_t SynchronizedExpandableMemoryPool<
getFreeSpaceCount()97     ElementType, kMemoryPoolSize, kMaxMemoryPoolCount>::getFreeSpaceCount() {
98   LockGuard<Mutex> lock(mMutex);
99   return kMaxMemoryPoolCount * kMemoryPoolSize - mSize;
100 }
101 
102 template <typename ElementType, size_t kMemoryPoolSize,
103           size_t kMaxMemoryPoolCount>
104 bool SynchronizedExpandableMemoryPool<ElementType, kMemoryPoolSize,
full()105                                       kMaxMemoryPoolCount>::full() {
106   LockGuard<Mutex> lock(mMutex);
107   return kMaxMemoryPoolCount * kMemoryPoolSize == mSize;
108 }
109 
110 template <typename ElementType, size_t kMemoryPoolSize,
111           size_t kMaxMemoryPoolCount>
112 size_t SynchronizedExpandableMemoryPool<ElementType, kMemoryPoolSize,
getBlockCount()113                                         kMaxMemoryPoolCount>::getBlockCount() {
114   LockGuard<Mutex> lock(mMutex);
115   return mMemoryPoolPtrs.size();
116 }
117 
118 template <typename ElementType, size_t kMemoryPoolSize,
119           size_t kMaxMemoryPoolCount>
120 bool SynchronizedExpandableMemoryPool<ElementType, kMemoryPoolSize,
pushOneBlock()121                                       kMaxMemoryPoolCount>::pushOneBlock() {
122   bool success = false;
123   if (mMemoryPoolPtrs.size() < kMaxMemoryPoolCount) {
124     auto newBlock = MakeUnique<Block>();
125     if (!newBlock.isNull()) {
126       success = true;
127       mMemoryPoolPtrs.push_back(std::move(newBlock));
128     }
129   }
130 
131   if (!success) {
132     LOG_OOM();
133   }
134 
135   return success;
136 }
137 
138 template <typename ElementType, size_t kMemoryPoolSize,
139           size_t kMaxMemoryPoolCount>
140 bool SynchronizedExpandableMemoryPool<
141     ElementType, kMemoryPoolSize,
isHalfFullBlock(Block * block)142     kMaxMemoryPoolCount>::isHalfFullBlock(Block *block) {
143   return block->getFreeBlockCount() < kMemoryPoolSize / 2;
144 }
145 }  // namespace chre
146 
147 #endif  // CHRE_UTIL_SYNCHRONIZED_EXPANDABLE_MEMORY_POOL_IMPL_H_
148