memory_pool_impl.h revision 4927ee586656424c827920876673228fbdcf27c3
1/*
2 * Copyright (C) 2016 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_MEMORY_POOL_IMPL_H_
18#define CHRE_UTIL_MEMORY_POOL_IMPL_H_
19
20#include "chre/util/memory_pool.h"
21
22#include <utility>
23
24/*
25 * TODO: needs to be thread safe (or there needs to be a thread safe version)
26 */
27
28namespace chre {
29
30template<typename ElementType, size_t kSize>
31MemoryPool<ElementType, kSize>::MemoryPool() {
32  // Initialize the free block list. The initial condition is such that each
33  // block points to the next as being empty. The mFreeBlockCount is used to
34  // ensure that we never allocate out of bounds so we don't need to worry about
35  // the last block referring to one that is non-existent.
36  for (size_t i = 0; i < kSize; i++) {
37    mBlocks.emplace_back(i + 1);
38  }
39}
40
41template<typename ElementType, size_t kSize>
42template<typename... Args>
43ElementType *MemoryPool<ElementType, kSize>::allocate(Args&&... args) {
44  if (mFreeBlockCount == 0) {
45    return nullptr;
46  }
47
48  size_t blockIndex = mNextFreeBlockIndex;
49  mNextFreeBlockIndex = mBlocks[blockIndex].mNextFreeBlockIndex;
50  mFreeBlockCount--;
51
52  return new (&mBlocks[blockIndex].mElement)
53      ElementType(std::forward<Args>(args)...);
54}
55
56template<typename ElementType, size_t kSize>
57void MemoryPool<ElementType, kSize>::deallocate(ElementType *element) {
58  uintptr_t elementAddress = reinterpret_cast<uintptr_t>(element);
59  uintptr_t baseAddress = reinterpret_cast<uintptr_t>(&mBlocks[0].mElement);
60  size_t blockIndex = (elementAddress - baseAddress) / sizeof(MemoryPoolBlock);
61
62  mBlocks[blockIndex].mElement.~ElementType();
63  mBlocks[blockIndex].mNextFreeBlockIndex = mNextFreeBlockIndex;
64  mNextFreeBlockIndex = blockIndex;
65  mFreeBlockCount++;
66}
67
68template<typename ElementType, size_t kSize>
69MemoryPool<ElementType, kSize>::MemoryPoolBlock::MemoryPoolBlock(
70    size_t nextFreeBlockIndex) : mNextFreeBlockIndex(nextFreeBlockIndex) {}
71
72}  // namespace chre
73
74#endif  // CHRE_UTIL_MEMORY_POOL_IMPL_H_
75