forked from boostorg/container
Implemented proposed resolution for LWG 3120
This commit is contained in:
@@ -1257,6 +1257,10 @@ use [*Boost.Container]? There are several reasons for that:
|
|||||||
found by Arthur O'Dowyer in his blog post
|
found by Arthur O'Dowyer in his blog post
|
||||||
[@https://quuxplusone.github.io/blog/2018/06/05/libcpp-memory-resource/ <memory_resource> for libc++]
|
[@https://quuxplusone.github.io/blog/2018/06/05/libcpp-memory-resource/ <memory_resource> for libc++]
|
||||||
|
|
||||||
|
* Implemented proposed resolution for
|
||||||
|
[@https://cplusplus.github.io/LWG/issue3120 ['"LWG 3120 Unclear behavior of monotonic_buffer_resource::release()"]].
|
||||||
|
After `release()` the original buffer is recovered for the next allocation.
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
[section:release_notes_boost_1_67_00 Boost 1.67 Release]
|
[section:release_notes_boost_1_67_00 Boost 1.67 Release]
|
||||||
|
@@ -54,6 +54,8 @@ class BOOST_CONTAINER_DECL monotonic_buffer_resource
|
|||||||
void * m_current_buffer;
|
void * m_current_buffer;
|
||||||
std::size_t m_current_buffer_size;
|
std::size_t m_current_buffer_size;
|
||||||
std::size_t m_next_buffer_size;
|
std::size_t m_next_buffer_size;
|
||||||
|
void * const m_initial_buffer;
|
||||||
|
std::size_t const m_initial_buffer_size;
|
||||||
|
|
||||||
/// @cond
|
/// @cond
|
||||||
void increase_next_buffer();
|
void increase_next_buffer();
|
||||||
@@ -131,7 +133,7 @@ class BOOST_CONTAINER_DECL monotonic_buffer_resource
|
|||||||
std::size_t remaining_storage(std::size_t alignment = 1u) const BOOST_NOEXCEPT;
|
std::size_t remaining_storage(std::size_t alignment = 1u) const BOOST_NOEXCEPT;
|
||||||
|
|
||||||
//! <b>Returns</b>:
|
//! <b>Returns</b>:
|
||||||
//! The number of bytes of storage available for the specified alignment.
|
//! The address pointing to the start of the current free storage.
|
||||||
//!
|
//!
|
||||||
//! <b>Note</b>: Non-standard extension.
|
//! <b>Note</b>: Non-standard extension.
|
||||||
const void *current_buffer() const BOOST_NOEXCEPT;
|
const void *current_buffer() const BOOST_NOEXCEPT;
|
||||||
|
@@ -63,6 +63,8 @@ monotonic_buffer_resource::monotonic_buffer_resource(memory_resource* upstream)
|
|||||||
, m_current_buffer(0)
|
, m_current_buffer(0)
|
||||||
, m_current_buffer_size(0u)
|
, m_current_buffer_size(0u)
|
||||||
, m_next_buffer_size(initial_next_buffer_size)
|
, m_next_buffer_size(initial_next_buffer_size)
|
||||||
|
, m_initial_buffer(0)
|
||||||
|
, m_initial_buffer_size(0u)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
monotonic_buffer_resource::monotonic_buffer_resource(std::size_t initial_size, memory_resource* upstream) BOOST_NOEXCEPT
|
monotonic_buffer_resource::monotonic_buffer_resource(std::size_t initial_size, memory_resource* upstream) BOOST_NOEXCEPT
|
||||||
@@ -70,6 +72,8 @@ monotonic_buffer_resource::monotonic_buffer_resource(std::size_t initial_size, m
|
|||||||
, m_current_buffer(0)
|
, m_current_buffer(0)
|
||||||
, m_current_buffer_size(0u)
|
, m_current_buffer_size(0u)
|
||||||
, m_next_buffer_size(minimum_buffer_size)
|
, m_next_buffer_size(minimum_buffer_size)
|
||||||
|
, m_initial_buffer(0)
|
||||||
|
, m_initial_buffer_size(0u)
|
||||||
{ //In case initial_size is zero
|
{ //In case initial_size is zero
|
||||||
this->increase_next_buffer_at_least_to(initial_size + !initial_size);
|
this->increase_next_buffer_at_least_to(initial_size + !initial_size);
|
||||||
}
|
}
|
||||||
@@ -81,6 +85,8 @@ monotonic_buffer_resource::monotonic_buffer_resource(void* buffer, std::size_t b
|
|||||||
, m_next_buffer_size
|
, m_next_buffer_size
|
||||||
(bi::detail::previous_or_equal_pow2
|
(bi::detail::previous_or_equal_pow2
|
||||||
(boost::container::dtl::max_value(buffer_size, std::size_t(initial_next_buffer_size))))
|
(boost::container::dtl::max_value(buffer_size, std::size_t(initial_next_buffer_size))))
|
||||||
|
, m_initial_buffer(buffer)
|
||||||
|
, m_initial_buffer_size(buffer_size)
|
||||||
{ this->increase_next_buffer(); }
|
{ this->increase_next_buffer(); }
|
||||||
|
|
||||||
monotonic_buffer_resource::~monotonic_buffer_resource()
|
monotonic_buffer_resource::~monotonic_buffer_resource()
|
||||||
@@ -89,8 +95,8 @@ monotonic_buffer_resource::~monotonic_buffer_resource()
|
|||||||
void monotonic_buffer_resource::release() BOOST_NOEXCEPT
|
void monotonic_buffer_resource::release() BOOST_NOEXCEPT
|
||||||
{
|
{
|
||||||
m_memory_blocks.release();
|
m_memory_blocks.release();
|
||||||
m_current_buffer = 0u;
|
m_current_buffer = m_initial_buffer;
|
||||||
m_current_buffer_size = 0u;
|
m_current_buffer_size = m_initial_buffer_size;
|
||||||
m_next_buffer_size = initial_next_buffer_size;
|
m_next_buffer_size = initial_next_buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -403,6 +403,7 @@ void test_do_is_equal()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void test_release()
|
void test_release()
|
||||||
|
{
|
||||||
{
|
{
|
||||||
memory_resource_logger mrl;
|
memory_resource_logger mrl;
|
||||||
const std::size_t initial_size = 1u;
|
const std::size_t initial_size = 1u;
|
||||||
@@ -420,6 +421,25 @@ void test_release()
|
|||||||
BOOST_TEST(mrl.m_mismatches == 0u);
|
BOOST_TEST(mrl.m_mismatches == 0u);
|
||||||
BOOST_TEST(mrl.m_info.size() == 0u);
|
BOOST_TEST(mrl.m_info.size() == 0u);
|
||||||
}
|
}
|
||||||
|
//Now use a local buffer
|
||||||
|
{
|
||||||
|
boost::move_detail::aligned_storage
|
||||||
|
<monotonic_buffer_resource::initial_next_buffer_size>::type buf;
|
||||||
|
//Supply an external buffer
|
||||||
|
monotonic_buffer_resource monr(&buf, sizeof(buf));
|
||||||
|
memory_resource &mr = monr;
|
||||||
|
BOOST_TEST(monr.remaining_storage(1u) == sizeof(buf));
|
||||||
|
//Allocate all remaining storage
|
||||||
|
mr.allocate(monr.remaining_storage(1u), 1u);
|
||||||
|
BOOST_TEST(monr.current_buffer() == ((char*)&buf + sizeof(buf)));
|
||||||
|
//No new allocation should have ocurred
|
||||||
|
BOOST_TEST(monr.remaining_storage(1u) == 0u);
|
||||||
|
//Release and check memory was released and the original buffer is back
|
||||||
|
monr.release();
|
||||||
|
BOOST_TEST(monr.remaining_storage(1u) == sizeof(buf));
|
||||||
|
BOOST_TEST(monr.current_buffer() == &buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void test_destructor()
|
void test_destructor()
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user