Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 37 additions & 5 deletions include/foonathan/memory/segregator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ namespace foonathan
{
namespace memory
{
enum class ThresholdAlignment : std::size_t
{
None, // No alignment limit
AllocatorMax // Use allocator's max_alignment
};

/// A \concept{concept_segregatable,Segregatable} that allocates until a maximum size.
/// \ingroup adapter
template <class RawAllocator>
Expand All @@ -29,24 +35,39 @@ namespace foonathan
/// and the allocator it uses.
explicit threshold_segregatable(std::size_t max_size,
allocator_type alloc = allocator_type())
: allocator_type(detail::move(alloc)), max_size_(max_size)
: allocator_type(detail::move(alloc)),
max_size_(max_size),
max_alignment_(static_cast<std::size_t>(-1))
{
}

/// \effects Creates it by passing the maximum size and alignment it will allocate,
/// and the allocator it uses.
explicit threshold_segregatable(std::size_t max_size, ThresholdAlignment alignment,
allocator_type alloc = allocator_type())
: allocator_type(detail::move(alloc)),
max_size_(max_size),
max_alignment_(alignment == ThresholdAlignment::AllocatorMax ?
allocator_traits<allocator_type>::max_alignment(get_allocator()) :
static_cast<std::size_t>(-1))
{
}

/// \returns `true` if `size` is less then or equal to the maximum size,
/// `false` otherwise.
/// \note A return value of `true` means that the allocator will be used for the allocation.
bool use_allocate_node(std::size_t size, std::size_t) noexcept
bool use_allocate_node(std::size_t size, std::size_t alignment) noexcept
{
return size <= max_size_;
return size <= max_size_ && alignment <= max_alignment_;
}

/// \returns `true` if `count * size` is less then or equal to the maximum size,
/// `false` otherwise.
/// \note A return value of `true` means that the allocator will be used for the allocation.
bool use_allocate_array(std::size_t count, std::size_t size, std::size_t) noexcept
bool use_allocate_array(std::size_t count, std::size_t size,
std::size_t alignment) noexcept
{
return count * size <= max_size_;
return count * size <= max_size_ && alignment <= max_alignment_;
}

/// @{
Expand All @@ -64,6 +85,7 @@ namespace foonathan

private:
std::size_t max_size_;
std::size_t max_alignment_;
};

/// \returns A \ref threshold_segregatable with the same parameter.
Expand All @@ -76,6 +98,16 @@ namespace foonathan
std::forward<RawAllocator>(alloc));
}

/// \returns A \ref threshold_segregatable with the same parameter.
template <class RawAllocator>
threshold_segregatable<typename std::decay<RawAllocator>::type> threshold(
std::size_t max_size, ThresholdAlignment alignment, RawAllocator&& alloc)
{
return threshold_segregatable<
typename std::decay<RawAllocator>::type>(max_size, alignment,
std::forward<RawAllocator>(alloc));
}

/// A composable \concept{concept_rawallocator,RawAllocator} that will always fail.
/// This is useful for compositioning or as last resort in \ref binary_segregator.
/// \ingroup allocator
Expand Down
15 changes: 15 additions & 0 deletions test/segregator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,21 @@ TEST_CASE("threshold_segregatable")
REQUIRE(s.use_allocate_array(2u, 4u, 1u));
REQUIRE(!s.use_allocate_array(2u, 8u, 1u));
REQUIRE(!s.use_allocate_array(1u, 9u, 1u));
REQUIRE(s.use_allocate_array(1u, 1u, 64u));

s = segregatable(8u, ThresholdAlignment::AllocatorMax);
REQUIRE(s.use_allocate_node(1u, 1u));
REQUIRE(s.use_allocate_node(8u, 1u));
REQUIRE(!s.use_allocate_node(8u, 100u));
REQUIRE(!s.use_allocate_node(9u, 1u));
REQUIRE(!s.use_allocate_node(9u, 100u));

REQUIRE(s.use_allocate_array(1u, 1u, 1u));
REQUIRE(s.use_allocate_array(1u, 8u, 1u));
REQUIRE(s.use_allocate_array(2u, 4u, 1u));
REQUIRE(!s.use_allocate_array(2u, 8u, 1u));
REQUIRE(!s.use_allocate_array(1u, 9u, 1u));
REQUIRE(!s.use_allocate_array(1u, 1u, 64u));
}

TEST_CASE("binary_segregator")
Expand Down