6#include <bond/core/config.h>
8#include "capped_allocator_fwd.h"
9#include "detail/value_or_reference.h"
10#include "multi_threaded_counter.h"
11#include "shared_counter.h"
12#include "single_threaded_counter.h"
14#include <bond/core/detail/alloc.h>
16#include <boost/utility/enable_if.hpp>
18namespace bond {
namespace ext
23 template <
typename Alloc,
typename Enable =
void>
27 template <
typename Alloc>
29 !std::is_void<typename Alloc::value_type>::value
30 && !(std::is_void<typename Alloc::reference>::value
31 || std::is_void<typename Alloc::const_reference>::value)>::type>
33 using reference =
typename Alloc::reference;
34 using const_reference =
typename Alloc::const_reference;
38 template <
typename Alloc>
40 !std::is_void<typename Alloc::value_type>::value
41 && (std::is_void<typename Alloc::reference>::value
42 || std::is_void<typename Alloc::const_reference>::value)>::type>
44 using reference =
typename Alloc::value_type&;
45 using const_reference =
const typename Alloc::value_type&;
49 template <
typename Alloc>
51 std::is_void<typename Alloc::value_type>>::type>
53 using reference = void;
54 using const_reference = void;
68 template <
typename Alloc,
typename Counter>
71 using holder =
typename capped_allocator::allocator_holder;
72 using traits = std::allocator_traits<Alloc>;
75 using value_type =
typename traits::value_type;
76 using pointer =
typename traits::pointer;
77 using const_pointer =
typename traits::const_pointer;
78 using void_pointer =
typename traits::void_pointer;
79 using const_void_pointer =
typename traits::const_void_pointer;
82 using size_type =
typename traits::size_type;
83 using difference_type =
typename traits::difference_type;
84 using propagate_on_container_copy_assignment =
typename traits::propagate_on_container_copy_assignment;
85 using propagate_on_container_move_assignment =
typename traits::propagate_on_container_move_assignment;
86 using propagate_on_container_swap =
typename traits::propagate_on_container_swap;
87#if __cplusplus >= 201703L
88 using is_always_equal =
typename traits::is_always_equal;
121 const Alloc& alloc = {},
122 bool subtract_on_deallocate =
true)
125 _subtract_on_deallocate{ subtract_on_deallocate }
139 template <
typename C = Counter,
140 typename boost::enable_if<std::uses_allocator<C, Alloc>>::type* =
nullptr>
142 typename C::value_type max_value,
143 const Alloc& alloc = {},
144 bool subtract_on_deallocate =
true)
145 :
capped_allocator{ Counter{ max_value, alloc }, alloc, subtract_on_deallocate }
149 template <
typename OtherAlloc,
150 typename boost::enable_if<std::is_convertible<OtherAlloc, Alloc>>::type* =
nullptr>
152 :
capped_allocator{ other._count, other.get_allocator(), other._subtract_on_deallocate }
155 pointer allocate(size_type n)
157 const auto size = n *
sizeof(value_type);
159 if (_count.get().try_add(size))
163 return traits::allocate(get_allocator(), n);
167 _count.get().subtract(size);
172 throw std::bad_alloc{};
175 pointer allocate(size_type n, const_void_pointer hint)
177 const auto size = n *
sizeof(value_type);
179 if (_count.get().try_add(size))
183 return traits::allocate(get_allocator(), n, hint);
187 _count.get().subtract(size);
192 throw std::bad_alloc{};
195 void deallocate(pointer ptr, size_type n)
197 traits::deallocate(get_allocator(), ptr, n);
199 if (_subtract_on_deallocate)
201 _count.get().subtract(n *
sizeof(value_type));
205 template <
typename T,
typename... Args>
206 void construct(T* ptr, Args&&... args)
208 traits::construct(get_allocator(), ptr, std::forward<Args>(args)...);
211 template <
typename T>
214 traits::destroy(get_allocator(), ptr);
217 size_type max_size() const BOND_NOEXCEPT
220 _count.get().max_value() /
sizeof(value_type),
221 traits::max_size(get_allocator()));
224 capped_allocator select_on_container_copy_construction()
226 return capped_allocator{
228 traits::select_on_container_copy_construction(get_allocator()),
229 _subtract_on_deallocate };
232 const Alloc& get_allocator() const BOND_NOEXCEPT
234 return holder::get();
237 Alloc& get_allocator() BOND_NOEXCEPT
239 return holder::get();
242 const Counter& get_counter() const BOND_NOEXCEPT
247 Counter& get_counter() BOND_NOEXCEPT
253 template <
typename OtherAlloc,
typename OtherCounter>
254 friend class capped_allocator;
256 detail::value_or_reference<Counter> _count;
257 bool _subtract_on_deallocate;
261 template <
typename Alloc,
typename Counter>
263 const capped_allocator<Alloc, Counter>& a1,
264 const capped_allocator<Alloc, Counter>& a2) BOND_NOEXCEPT
266 return a1.get_allocator() == a2.get_allocator();
269 template <
typename Alloc,
typename Counter>
270 inline bool operator!=(
271 const capped_allocator<Alloc, Counter>& a1,
272 const capped_allocator<Alloc, Counter>& a2) BOND_NOEXCEPT
274 return a1.get_allocator() != a2.get_allocator();
Helper type that holds an allocator.
Definition: alloc.h:22
Definition: capped_allocator.h:70
capped_allocator(const capped_allocator< OtherAlloc, Counter > &other)
Converts from a compatible allocator.
Definition: capped_allocator.h:151
capped_allocator(detail::value_or_reference< Counter > count, const Alloc &alloc={}, bool subtract_on_deallocate=true)
Constructs capped allocator adapter.
Definition: capped_allocator.h:119
capped_allocator(typename C::value_type max_value, const Alloc &alloc={}, bool subtract_on_deallocate=true)
Constructs capped allocator adapter.
Definition: capped_allocator.h:141
Helper type that can hold either a value or a reference.
Definition: value_or_reference.h:20
namespace bond
Definition: apply.h:17
boost::enable_if< is_signed_int_or_enum< SignedT >, bool >::type operator==(const Variant &variant, SignedT value)
Compares variant for equality against the provided signed integer or enum value.
Definition: metadata.h:24
Helper type to deal with types that are not C++11 conformant.
Definition: capped_allocator.h:24