File indexing completed on 2024-04-06 12:31:41
0001 #ifndef Tracker_ChurnAllocator_H
0002 #define Tracker_ChurnAllocator_H
0003 #include <memory>
0004
0005 template <typename T>
0006 class churn_allocator : public std::allocator<T> {
0007 public:
0008 using Base = std::allocator<T>;
0009 using pointer = typename std::allocator_traits<std::allocator<T>>::pointer;
0010 using size_type = typename Base::size_type;
0011
0012 struct Cache {
0013 pointer cache = nullptr;
0014 bool gard = false;
0015 };
0016
0017 static Cache &cache() {
0018 static thread_local Cache local;
0019 return local;
0020 }
0021
0022 template <typename _Tp1>
0023 struct rebind {
0024 typedef churn_allocator<_Tp1> other;
0025 };
0026
0027 pointer allocate(size_type n) {
0028 Cache &c = cache();
0029 if (!c.gard)
0030 c.cache = std::allocator<T>::allocate(n);
0031 c.gard = false;
0032 return c.cache;
0033 }
0034
0035 void deallocate(pointer p, size_type n) {
0036 Cache &c = cache();
0037 if (p == c.cache)
0038 c.gard = true;
0039 else
0040 std::allocator<T>::deallocate(p, n);
0041 }
0042
0043 churn_allocator() = default;
0044 churn_allocator(churn_allocator const &) = default;
0045 churn_allocator(churn_allocator &&) = default;
0046
0047 template <class U>
0048 churn_allocator(const churn_allocator<U> &a) noexcept : std::allocator<T>(a) {}
0049 };
0050
0051 #endif