/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * 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 * * http://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. */ #pragma once #include #include #include #include #include #include #include #include #include using PmrByteAlloc = std::pmr::polymorphic_allocator; template struct AlwaysThrowAllocator : private std::allocator { using value_type = T; AlwaysThrowAllocator() = default; AlwaysThrowAllocator(const AlwaysThrowAllocator&) noexcept = default; AlwaysThrowAllocator& operator=(const AlwaysThrowAllocator&) noexcept = default; template explicit AlwaysThrowAllocator(const AlwaysThrowAllocator&) noexcept {} ~AlwaysThrowAllocator() = default; T* allocate(size_t) { throw std::bad_alloc(); } void deallocate(T*, size_t) {} template friend bool operator==( const AlwaysThrowAllocator&, const AlwaysThrowAllocator&) noexcept { return true; } template friend bool operator!=( const AlwaysThrowAllocator&, const AlwaysThrowAllocator&) noexcept { return false; } }; template using ScopedAlwaysThrowAlloc = std::scoped_allocator_adaptor>; template using AlwaysThrowVector = std::vector>; template using AlwaysThrowSet = std::set, ScopedAlwaysThrowAlloc>; template using AlwaysThrowMap = std::map, ScopedAlwaysThrowAlloc>>; using AlwaysThrowString = std::basic_string, ScopedAlwaysThrowAlloc<>>; template using AlwaysThrowUniquePtr = std::unique_ptr< T, folly::allocator_delete< std::scoped_allocator_adaptor>>>; template struct StatefulAlloc : private std::allocator { using value_type = T; StatefulAlloc() = default; StatefulAlloc(const StatefulAlloc&) = default; StatefulAlloc& operator=(const StatefulAlloc&) noexcept = default; explicit StatefulAlloc(int state) : state_(state) {} template explicit StatefulAlloc(const StatefulAlloc& other) noexcept : state_(other.state_) {} int state_ = 0; T* allocate(size_t size) { return std::allocator::allocate(size); } void deallocate(T* p, size_t size) { std::allocator::deallocate(p, size); } template friend bool operator==( const StatefulAlloc& a, const StatefulAlloc& b) noexcept { return a.state_ == b.state_; } template friend bool operator!=( const StatefulAlloc& a, const StatefulAlloc& b) noexcept { return a.state_ != b.state_; } }; template using ScopedStatefulAlloc = std::scoped_allocator_adaptor>; template using StatefulAllocVector = std::vector>; template using StatefulAllocSet = std::set, ScopedStatefulAlloc>; template using StatefulAllocMap = std::map, ScopedStatefulAlloc>>; template using StatefulAllocSortedVectorSet = folly::sorted_vector_set, ScopedStatefulAlloc>; template using StatefulAllocSortedVectorMap = folly:: sorted_vector_map, ScopedStatefulAlloc>>; template struct CountingAlloc : private std::allocator { using value_type = T; CountingAlloc() : counter_(std::make_shared(0)) {} CountingAlloc(const CountingAlloc&) = default; CountingAlloc& operator=(const CountingAlloc&) noexcept = default; template explicit CountingAlloc(const CountingAlloc& other) noexcept : counter_(other.counter_) {} std::shared_ptr counter_; int getCount() const { return *counter_; } T* allocate(size_t size) { (*counter_)++; return std::allocator::allocate(size); } void deallocate(T* p, size_t size) { std::allocator::deallocate(p, size); } template friend bool operator==( const CountingAlloc& a, const CountingAlloc& b) noexcept { return a.counter_.get() == b.counter_.get(); // both point to same counter } template friend bool operator!=( const CountingAlloc& a, const CountingAlloc& b) noexcept { return !(a == b); } }; template using ScopedCountingAlloc = std::scoped_allocator_adaptor>; template using CountingVector = std::vector>; template using CountingSet = std::set, ScopedCountingAlloc>; template using CountingMap = std::map, ScopedCountingAlloc>>; using CountingString = std::basic_string, ScopedCountingAlloc<>>; struct CountingPmrResource : public std::pmr::memory_resource { CountingPmrResource() : counter_(std::make_shared(0)) {} CountingPmrResource(const CountingPmrResource&) = default; CountingPmrResource& operator=(const CountingPmrResource&) = default; int getCount() const { return *counter_; } private: std::shared_ptr counter_; void* do_allocate(size_t bytes, size_t alignment) override { (*counter_)++; return std::pmr::get_default_resource()->allocate(bytes, alignment); } void do_deallocate(void* p, size_t bytes, size_t alignment) override { std::pmr::get_default_resource()->deallocate(p, bytes, alignment); } bool do_is_equal(const memory_resource&) const noexcept override { return true; } }; using PropagateAllocBase = StatefulAlloc; struct PropagateAllAlloc : public PropagateAllocBase { using PropagateAllocBase::PropagateAllocBase; using propagate_on_container_copy_assignment = std::true_type; using propagate_on_container_move_assignment = std::true_type; using propagate_on_container_swap = std::true_type; }; struct PropagateNoneAlloc : public PropagateAllocBase { using PropagateAllocBase::PropagateAllocBase; using propagate_on_container_copy_assignment = std::false_type; using propagate_on_container_move_assignment = std::false_type; using propagate_on_container_swap = std::false_type; PropagateNoneAlloc(const PropagateNoneAlloc&) = default; PropagateNoneAlloc(PropagateNoneAlloc&&) = default; PropagateNoneAlloc& operator=(const PropagateNoneAlloc&) = delete; PropagateNoneAlloc& operator=(PropagateNoneAlloc&&) = delete; }; struct PropagateOnlyCopyAlloc : public PropagateAllocBase { using PropagateAllocBase::PropagateAllocBase; using propagate_on_container_copy_assignment = std::true_type; using propagate_on_container_move_assignment = std::false_type; using propagate_on_container_swap = std::false_type; PropagateOnlyCopyAlloc(const PropagateOnlyCopyAlloc&) = default; PropagateOnlyCopyAlloc(PropagateOnlyCopyAlloc&&) = default; PropagateOnlyCopyAlloc& operator=(const PropagateOnlyCopyAlloc&) = default; PropagateOnlyCopyAlloc& operator=(PropagateOnlyCopyAlloc&&) = delete; }; struct PropagateOnlyMoveAlloc : public PropagateAllocBase { using PropagateAllocBase::PropagateAllocBase; using propagate_on_container_copy_assignment = std::false_type; using propagate_on_container_move_assignment = std::true_type; using propagate_on_container_swap = std::false_type; PropagateOnlyMoveAlloc(const PropagateOnlyMoveAlloc&) = default; PropagateOnlyMoveAlloc(PropagateOnlyMoveAlloc&&) = default; PropagateOnlyMoveAlloc& operator=(const PropagateOnlyMoveAlloc&) = delete; PropagateOnlyMoveAlloc& operator=(PropagateOnlyMoveAlloc&&) = default; }; struct PropagateOnlySwapAlloc : public PropagateAllocBase { using PropagateAllocBase::PropagateAllocBase; using propagate_on_container_copy_assignment = std::false_type; using propagate_on_container_move_assignment = std::false_type; using propagate_on_container_swap = std::true_type; }; struct PropagateCopyMoveAlloc : public PropagateAllocBase { using PropagateAllocBase::PropagateAllocBase; using propagate_on_container_copy_assignment = std::true_type; using propagate_on_container_move_assignment = std::true_type; using propagate_on_container_swap = std::false_type; }; struct PropagateCopySwapAlloc : public PropagateAllocBase { using PropagateAllocBase::PropagateAllocBase; using propagate_on_container_copy_assignment = std::true_type; using propagate_on_container_move_assignment = std::false_type; using propagate_on_container_swap = std::true_type; }; struct PropagateMoveSwapAlloc : public PropagateAllocBase { using PropagateAllocBase::PropagateAllocBase; using propagate_on_container_copy_assignment = std::false_type; using propagate_on_container_move_assignment = std::true_type; using propagate_on_container_swap = std::true_type; PropagateMoveSwapAlloc(const PropagateMoveSwapAlloc&) = default; PropagateMoveSwapAlloc(PropagateMoveSwapAlloc&&) = default; PropagateMoveSwapAlloc& operator=(const PropagateMoveSwapAlloc&) = delete; PropagateMoveSwapAlloc& operator=(PropagateMoveSwapAlloc&&) = default; }; template using CountingUniquePtr = std::unique_ptr< T, folly::allocator_delete>>>;