| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 | // Copyright 2018 The Abseil Authors.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at////      https://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.#ifndef ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_#define ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_#include <cstdint>#include <memory>#include "absl/base/config.h"namespace absl {ABSL_NAMESPACE_BEGINnamespace container_internal {// This is a stateful allocator, but the state lives outside of the// allocator (in whatever test is using the allocator). This is odd// but helps in tests where the allocator is propagated into nested// containers - that chain of allocators uses the same state and is// thus easier to query for aggregate allocation information.template <typename T>class CountingAllocator { public:  using Allocator = std::allocator<T>;  using AllocatorTraits = std::allocator_traits<Allocator>;  using value_type = typename AllocatorTraits::value_type;  using pointer = typename AllocatorTraits::pointer;  using const_pointer = typename AllocatorTraits::const_pointer;  using size_type = typename AllocatorTraits::size_type;  using difference_type = typename AllocatorTraits::difference_type;  CountingAllocator() = default;  explicit CountingAllocator(int64_t* bytes_used) : bytes_used_(bytes_used) {}  CountingAllocator(int64_t* bytes_used, int64_t* instance_count)      : bytes_used_(bytes_used), instance_count_(instance_count) {}  template <typename U>  CountingAllocator(const CountingAllocator<U>& x)      : bytes_used_(x.bytes_used_), instance_count_(x.instance_count_) {}  pointer allocate(      size_type n,      typename AllocatorTraits::const_void_pointer hint = nullptr) {    Allocator allocator;    pointer ptr = AllocatorTraits::allocate(allocator, n, hint);    if (bytes_used_ != nullptr) {      *bytes_used_ += n * sizeof(T);    }    return ptr;  }  void deallocate(pointer p, size_type n) {    Allocator allocator;    AllocatorTraits::deallocate(allocator, p, n);    if (bytes_used_ != nullptr) {      *bytes_used_ -= n * sizeof(T);    }  }  template <typename U, typename... Args>  void construct(U* p, Args&&... args) {    Allocator allocator;    AllocatorTraits::construct(allocator, p, std::forward<Args>(args)...);    if (instance_count_ != nullptr) {      *instance_count_ += 1;    }  }  template <typename U>  void destroy(U* p) {    Allocator allocator;    AllocatorTraits::destroy(allocator, p);    if (instance_count_ != nullptr) {      *instance_count_ -= 1;    }  }  template <typename U>  class rebind {   public:    using other = CountingAllocator<U>;  };  friend bool operator==(const CountingAllocator& a,                         const CountingAllocator& b) {    return a.bytes_used_ == b.bytes_used_ &&           a.instance_count_ == b.instance_count_;  }  friend bool operator!=(const CountingAllocator& a,                         const CountingAllocator& b) {    return !(a == b);  }  int64_t* bytes_used_ = nullptr;  int64_t* instance_count_ = nullptr;};}  // namespace container_internalABSL_NAMESPACE_END}  // namespace absl#endif  // ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
 |