memory_pool.h revision a51ef01822ac68061a1d6e686389cfbcb0e1f8da
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_H_
18#define CHRE_UTIL_MEMORY_POOL_H_
19
20#include <cstddef>
21#include <type_traits>
22
23#include "chre/util/non_copyable.h"
24
25namespace chre {
26
27/**
28 * A memory pool (slab allocator) used for very efficient allocation and
29 * deallocation of objects with a uniform size. The goal is to avoid costly
30 * malloc/free calls.
31 *
32 * This implementation is based on the following paper:
33 *
34 * Fast Efficient Fixed-Size Memory Pool
35 * No Loops and No Overhead
36 * Ben Kenwright
37 *
38 * Allocations and deallocation are handled in O(1) time and memory. The list
39 * of unused blocks is stored in the space of unused blocks. This means that
40 * this data structure has a minimum element size of sizeof(size_t) and means
41 * it may not be suitable for very small objects (whose size is less than
42 * sizeof(size_t)).
43 *
44 * One variation is made relative to the allocator described in the paper. To
45 * minimize allocation/deallocation latency, the free list is built at
46 * construction time.
47 */
48template<typename ElementType, size_t kSize>
49class MemoryPool : public NonCopyable {
50 public:
51  /**
52   * Constructs a MemoryPool and initializes the initial conditions of the
53   * allocator.
54   */
55  MemoryPool();
56
57  /**
58   * Allocates space for an object, constructs it and returns the pointer to
59   * that object.
60   *
61   * @param  The arguments to be forwarded to the constructor of the object.
62   * @return A pointer to a constructed object or nullptr if the allocation
63   *         fails.
64   */
65  template<typename... Args>
66  ElementType *allocate(Args&&... args);
67
68  /**
69   * Releases the memory of a previously allocated element. The pointer provided
70   * here must be one that was produced by a previous call to the allocate()
71   * function. The destructor is invoked on the object.
72   *
73   * @param A pointer to an element that was previously allocated by the
74   *        allocate() function.
75   */
76  void deallocate(ElementType *element);
77
78 private:
79  /**
80   * The unused storage for this MemoryPool maintains the list of free slots.
81   * As such, a union is used to allow storage of both the Element and the index
82   * of the next free block in the same space.
83   */
84  union MemoryPoolBlock {
85    //! Intentionally not destructing any leaked blocks, will consider doing
86    //! this differently later if required.
87    ~MemoryPoolBlock() = delete;
88
89    //! The element stored in the slot.
90    ElementType mElement;
91
92    //! The index of the next free block in the unused storage.
93    size_t mNextFreeBlockIndex;
94  };
95
96  /**
97   * Obtains a pointer to the underlying storage for the memory pool blocks.
98   *
99   * @return A pointer to the memory pool block storage.
100   */
101  MemoryPoolBlock *blocks();
102
103  //! Storage for memory pool blocks. To avoid static initialization of members,
104  //! std::aligned_storage is used.
105  typename std::aligned_storage<sizeof(MemoryPoolBlock),
106      alignof(MemoryPoolBlock)>::type mBlocks[kSize];
107
108  //! The index of the head of the free slot list.
109  size_t mNextFreeBlockIndex = 0;
110
111  //! The number of free slots available.
112  size_t mFreeBlockCount = kSize;
113};
114
115}  // namespace chre
116
117#include "chre/util/memory_pool_impl.h"
118
119#endif  // CHRE_UTIL_MEMORY_POOL_H_
120