00001 // Copyright 2018 The Abseil Authors. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); 00004 // you may not use this file except in compliance with the License. 00005 // You may obtain a copy of the License at 00006 // 00007 // https://www.apache.org/licenses/LICENSE-2.0 00008 // 00009 // Unless required by applicable law or agreed to in writing, software 00010 // distributed under the License is distributed on an "AS IS" BASIS, 00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 // See the License for the specific language governing permissions and 00013 // limitations under the License. 00014 00015 #ifndef ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_ 00016 #define ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_ 00017 00018 #include <cassert> 00019 #include <cstdint> 00020 #include <memory> 00021 00022 namespace absl { 00023 namespace container_internal { 00024 00025 // This is a stateful allocator, but the state lives outside of the 00026 // allocator (in whatever test is using the allocator). This is odd 00027 // but helps in tests where the allocator is propagated into nested 00028 // containers - that chain of allocators uses the same state and is 00029 // thus easier to query for aggregate allocation information. 00030 template <typename T> 00031 class CountingAllocator : public std::allocator<T> { 00032 public: 00033 using Alloc = std::allocator<T>; 00034 using pointer = typename Alloc::pointer; 00035 using size_type = typename Alloc::size_type; 00036 00037 CountingAllocator() : bytes_used_(nullptr) {} 00038 explicit CountingAllocator(int64_t* b) : bytes_used_(b) {} 00039 00040 template <typename U> 00041 CountingAllocator(const CountingAllocator<U>& x) 00042 : Alloc(x), bytes_used_(x.bytes_used_) {} 00043 00044 pointer allocate(size_type n, 00045 std::allocator<void>::const_pointer hint = nullptr) { 00046 assert(bytes_used_ != nullptr); 00047 *bytes_used_ += n * sizeof(T); 00048 return Alloc::allocate(n, hint); 00049 } 00050 00051 void deallocate(pointer p, size_type n) { 00052 Alloc::deallocate(p, n); 00053 assert(bytes_used_ != nullptr); 00054 *bytes_used_ -= n * sizeof(T); 00055 } 00056 00057 template<typename U> 00058 class rebind { 00059 public: 00060 using other = CountingAllocator<U>; 00061 }; 00062 00063 friend bool operator==(const CountingAllocator& a, 00064 const CountingAllocator& b) { 00065 return a.bytes_used_ == b.bytes_used_; 00066 } 00067 00068 friend bool operator!=(const CountingAllocator& a, 00069 const CountingAllocator& b) { 00070 return !(a == b); 00071 } 00072 00073 int64_t* bytes_used_; 00074 }; 00075 00076 } // namespace container_internal 00077 } // namespace absl 00078 00079 #endif // ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_