1 /* 2 * Copyright 2014 Google Inc. All rights reserved. 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 FRUIT_MEMORY_POOL_DEFN_H 18 #define FRUIT_MEMORY_POOL_DEFN_H 19 20 #include <fruit/impl/data_structures/memory_pool.h> 21 #include <fruit/impl/fruit-config.h> 22 #include <fruit/impl/fruit_assert.h> 23 24 #include <cstdint> 25 26 namespace fruit { 27 namespace impl { 28 MemoryPool()29inline MemoryPool::MemoryPool() : first_free(nullptr), capacity(0) {} 30 MemoryPool(MemoryPool && other)31inline MemoryPool::MemoryPool(MemoryPool&& other) 32 : allocated_chunks(std::move(other.allocated_chunks)), first_free(other.first_free), capacity(other.capacity) { 33 // This is to be sure that we don't double-deallocate. 34 other.allocated_chunks.clear(); 35 } 36 37 inline MemoryPool& MemoryPool::operator=(MemoryPool&& other) { 38 destroy(); 39 40 allocated_chunks = std::move(other.allocated_chunks); 41 first_free = other.first_free; 42 capacity = other.capacity; 43 44 // This is to be sure that we don't double-deallocate. 45 other.allocated_chunks.clear(); 46 47 return *this; 48 } 49 ~MemoryPool()50inline MemoryPool::~MemoryPool() { 51 destroy(); 52 } 53 54 template <typename T> allocate(std::size_t n)55FRUIT_ALWAYS_INLINE inline T* MemoryPool::allocate(std::size_t n) { 56 #if FRUIT_DISABLE_ARENA_ALLOCATION 57 void* p = operator new(n * sizeof(T)); 58 allocated_chunks.push_back(p); 59 return static_cast<T*>(p); 60 #else 61 62 if (n == 0) { 63 n = 1; 64 } 65 std::size_t misalignment = std::uintptr_t(first_free) % alignof(T); 66 std::size_t padding = alignof(T) - (sizeof(T) % alignof(T)); 67 std::size_t required_space = n * (sizeof(T) + padding); 68 std::size_t required_space_in_chunk = required_space + (alignof(T) - misalignment); 69 if (required_space_in_chunk > capacity) { 70 // This is to make sure that the push_back below won't throw. 71 if (allocated_chunks.size() == allocated_chunks.capacity()) { 72 allocated_chunks.reserve(1 + 2 * allocated_chunks.size()); 73 } 74 void* p; 75 if (required_space > CHUNK_SIZE) { 76 p = operator new(required_space); // LCOV_EXCL_BR_LINE 77 } else { 78 p = operator new(CHUNK_SIZE); 79 first_free = static_cast<char*>(p) + required_space; 80 capacity = CHUNK_SIZE - required_space; 81 } 82 allocated_chunks.push_back(p); 83 return static_cast<T*>(p); 84 } else { 85 FruitAssert(first_free != nullptr); 86 void* p = first_free + misalignment; 87 first_free += required_space_in_chunk; 88 capacity -= required_space_in_chunk; 89 return static_cast<T*>(p); 90 } 91 #endif 92 } 93 94 } // namespace impl 95 } // namespace fruit 96 97 #endif // FRUIT_MEMORY_POOL_DEFN_H 98