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 BERBERIS_BASE_FOREVER_POOL_H_ 18 #define BERBERIS_BASE_FOREVER_POOL_H_ 19 20 #include <cstddef> 21 22 #include "berberis/base/forever_alloc.h" 23 #include "berberis/base/lock_free_stack.h" 24 25 namespace berberis { 26 27 // Memory pool to be used by berberis runtime. 28 // To be used for small objects of few different types. 29 // Thread-safe, signal-safe, reentrant. 30 // Singleton interface (no non-static members). 31 template <typename T> 32 class ForeverPool { 33 public: Alloc()34 static T* Alloc() { 35 Node* p = g_free_list_.Pop(); 36 if (p) { 37 return reinterpret_cast<T*>(p); 38 } 39 return reinterpret_cast<T*>(AllocateForever(sizeof(Node), alignof(Node))); 40 } 41 Free(T * p)42 static void Free(T* p) { g_free_list_.Push(reinterpret_cast<Node*>(p)); } 43 44 private: 45 // LockFreeStack requires 'next' data member. 46 union Node { 47 Node* next; 48 T value; 49 }; 50 51 static LockFreeStack<Node> g_free_list_; 52 53 ForeverPool() = delete; 54 }; 55 56 template <typename T> 57 LockFreeStack<typename ForeverPool<T>::Node> ForeverPool<T>::g_free_list_; 58 59 // Allocator for STL containers on top of berberis runtime's memory pool. 60 // ATTENTION: if allocate/deallocate more than 1 element at once, memory is NOT reused! 61 template <class T> 62 class ForeverPoolAllocator { 63 public: 64 using value_type = T; 65 ForeverPoolAllocator()66 ForeverPoolAllocator() {} 67 68 template <typename U> ForeverPoolAllocator(const ForeverPoolAllocator<U> &)69 ForeverPoolAllocator(const ForeverPoolAllocator<U>&) {} 70 allocate(size_t n)71 T* allocate(size_t n) { 72 if (n == 1) { 73 return ForeverPool<T>::Alloc(); 74 } else { 75 // ATTENTION: allocate directly from underlying ForeverAllocator! 76 return static_cast<T*>(AllocateForever(n * sizeof(T), alignof(T))); 77 } 78 } 79 deallocate(T * p,size_t n)80 void deallocate(T* p, size_t n) { 81 if (n == 1) { 82 ForeverPool<T>::Free(p); 83 } else { 84 // ATTENTION: waste! 85 } 86 } 87 88 bool operator==(const ForeverPoolAllocator<T>&) const { return true; } 89 90 bool operator!=(const ForeverPoolAllocator<T>&) const { return false; } 91 }; 92 93 } // namespace berberis 94 95 #endif // BERBERIS_BASE_FOREVER_POOL_H_ 96