Merge branch 'hotfix/fix-moved-containers-with-share-pools' into development

This commit is contained in:
John Wellbelove 2020-07-30 12:53:14 +01:00
commit eb2902de88
8 changed files with 409 additions and 76 deletions

View File

@ -1478,23 +1478,50 @@ namespace etl
{
this->initialise();
node_t* p_last_node = &start_node;
etl::iforward_list<T>::iterator first = rhs.begin();
etl::iforward_list<T>::iterator last = rhs.end();
// Add all of the elements.
while (first != last)
if (!rhs.empty())
{
ETL_ASSERT(!full(), ETL_ERROR(forward_list_full));
node_t* p_last_node = &this->start_node;
node_t* p_rhs_node = rhs.start_node.next;
data_node_t& data_node = this->allocate_data_node(etl::move(*first++));
join(p_last_node, &data_node);
data_node.next = ETL_NULLPTR;
p_last_node = &data_node;
// Are we using the same pool?
if (this->get_node_pool() == rhs.get_node_pool())
{
// Just link the nodes to the new forward_list.
do
{
node_t* p_node = p_rhs_node;
p_rhs_node = p_rhs_node->next;
insert_node_after(*p_last_node, *p_node);
p_last_node = p_node;
ETL_INCREMENT_DEBUG_COUNT;
} while (p_rhs_node != ETL_NULLPTR);
rhs.ETL_RESET_DEBUG_COUNT;
rhs.start_node.next = ETL_NULLPTR;
}
else
{
// Add all of the elements.
etl::iforward_list<T>::iterator first = rhs.begin();
etl::iforward_list<T>::iterator last = rhs.end();
while (first != last)
{
ETL_ASSERT(!full(), ETL_ERROR(forward_list_full));
data_node_t& data_node = this->allocate_data_node(etl::move(*first++));
join(p_last_node, &data_node);
data_node.next = ETL_NULLPTR;
p_last_node = &data_node;
}
rhs.initialise();
}
}
rhs.initialise();
}
}
#endif
@ -1762,7 +1789,7 @@ namespace etl
}
//*************************************************************************
/// Copy constructor.
/// Copy constructor. Implicit pool.
//*************************************************************************
forward_list(const forward_list& other)
: etl::iforward_list<T>(*other.p_node_pool, other.p_node_pool->max_size(), true)
@ -1770,26 +1797,32 @@ namespace etl
this->assign(other.cbegin(), other.cend());
}
//*************************************************************************
/// Copy constructor. Explicit pool.
//*************************************************************************
forward_list(const forward_list& other, etl::ipool& node_pool)
: etl::iforward_list<T>(node_pool, node_pool.max_size(), true)
{
this->assign(other.cbegin(), other.cend());
}
#if ETL_CPP11_SUPPORTED
//*************************************************************************
/// Move constructor.
/// Move constructor. Implicit pool
//*************************************************************************
forward_list(forward_list&& other)
: etl::iforward_list<T>(*other.p_node_pool, other.p_node_pool->max_size(), true)
{
if (this != &other)
{
this->initialise();
this->move_container(std::move(other));
}
typename etl::iforward_list<T>::iterator itr = other.begin();
while (itr != other.end())
{
this->push_back(etl::move(*itr));
++itr;
}
other.initialise();
}
//*************************************************************************
/// Move constructor. Explicit pool
//*************************************************************************
forward_list(forward_list&& other, etl::ipool& node_pool)
: etl::iforward_list<T>(node_pool, node_pool.max_size(), true)
{
this->move_container(std::move(other));
}
#endif
@ -1860,6 +1893,14 @@ namespace etl
this->set_node_pool(pool);
}
//*************************************************************************
/// Get the pool instance.
//*************************************************************************
etl::ipool& get_pool() const
{
return *this->p_node_pool;
}
};
//*************************************************************************

View File

@ -1829,6 +1829,59 @@ namespace etl
join(terminal_node, terminal_node);
}
#if ETL_CPP11_SUPPORTED
//*************************************************************************
/// Move a forward list
//*************************************************************************
void move_container(ilist&& rhs)
{
if (&rhs != this)
{
this->initialise();
if (!rhs.empty())
{
// Are we using the same pool?
if (this->get_node_pool() == rhs.get_node_pool())
{
node_t* p_rhs_node = &rhs.get_head();
// Just link the nodes to the new forward_list.
do
{
ETL_ASSERT(!full(), ETL_ERROR(list_full));
node_t* p_node = p_rhs_node;
p_rhs_node = p_rhs_node->next;
insert_node(terminal_node, *p_node);
ETL_INCREMENT_DEBUG_COUNT;
} while (p_rhs_node != &rhs.terminal_node);
rhs.ETL_RESET_DEBUG_COUNT;
rhs.join(rhs.terminal_node, rhs.terminal_node);
}
else
{
// Add all of the elements.
etl::ilist<T>::iterator first = rhs.begin();
etl::ilist<T>::iterator last = rhs.end();
while (first != last)
{
ETL_ASSERT(!full(), ETL_ERROR(list_full));
insert_node(terminal_node, this->allocate_data_node(etl::move(*first++)));
}
rhs.initialise();
}
}
}
}
#endif
private:
//*************************************************************************
@ -2090,23 +2143,11 @@ namespace etl
#if ETL_CPP11_SUPPORTED
//*************************************************************************
/// Assignment operator.
/// Move assignment operator.
//*************************************************************************
list& operator = (list&& rhs)
{
if (&rhs != this)
{
this->initialise();
typename etl::ilist<T>::iterator itr = rhs.begin();
while (itr != rhs.end())
{
this->push_back(etl::move(*itr));
++itr;
}
rhs.initialise();
}
this->move_container(etl::move(rhs));
return *this;
}
@ -2178,7 +2219,7 @@ namespace etl
}
//*************************************************************************
/// Copy constructor.
/// Copy constructor. Implicit pool.
//*************************************************************************
list(const list& other)
: etl::ilist<T>(*other.p_node_pool, other.p_node_pool->max_size(), true)
@ -2189,26 +2230,35 @@ namespace etl
}
}
//*************************************************************************
/// Copy constructor. Explicit pool.
//*************************************************************************
list(const list& other, etl::ipool& node_pool)
: etl::ilist<T>(node_pool, node_pool.max_size(), true)
{
if (this != &other)
{
this->assign(other.cbegin(), other.cend());
}
}
#if ETL_CPP11_SUPPORTED
//*************************************************************************
/// Move constructor.
/// Move constructor. Implicit pool.
//*************************************************************************
list(list&& other)
: etl::ilist<T>(*other.p_node_pool, other.p_node_pool->max_size(), true)
{
if (this != &other)
{
this->initialise();
this->move_container(etl::move(other));
}
typename etl::ilist<T>::iterator itr = other.begin();
while (itr != other.end())
{
this->push_back(etl::move(*itr));
++itr;
}
other.initialise();
}
//*************************************************************************
/// Move constructor. Explicit pool.
//*************************************************************************
list(list&& other, etl::ipool& node_pool)
: etl::ilist<T>(node_pool, node_pool.max_size(), true)
{
this->move_container(etl::move(other));
}
#endif
@ -2252,19 +2302,7 @@ namespace etl
//*************************************************************************
list& operator = (list&& rhs)
{
if (&rhs != this)
{
this->initialise();
typename etl::ilist<T>::iterator itr = rhs.begin();
while (itr != rhs.end())
{
this->push_back(etl::move(*itr));
++itr;
}
rhs.initialise();
}
this->move_container(etl::move(rhs));
return *this;
}
@ -2283,6 +2321,14 @@ namespace etl
this->set_node_pool(pool);
}
//*************************************************************************
/// Get the pool instance.
//*************************************************************************
etl::ipool& get_pool() const
{
return *this->p_node_pool;
}
};
//*************************************************************************

View File

@ -39,7 +39,7 @@ SOFTWARE.
#define ETL_VERSION_MAJOR 18
#define ETL_VERSION_MINOR 11
#define ETL_VERSION_PATCH 0
#define ETL_VERSION_PATCH 1
#define ETL_VERSION ETL_STRINGIFY(ETL_VERSION_MAJOR) "." ETL_STRINGIFY(ETL_VERSION_MINOR) "." ETL_STRINGIFY(ETL_VERSION_PATCH)
#define ETL_VERSION_W ETL_STRINGIFY(ETL_VERSION_MAJOR) L"." ETL_STRINGIFY(ETL_VERSION_MINOR) L"." ETL_STRINGIFY(ETL_VERSION_PATCH)
#define ETL_VERSION_U16 ETL_STRINGIFY(ETL_VERSION_MAJOR) u"." ETL_STRINGIFY(ETL_VERSION_MINOR) u"." ETL_STRINGIFY(ETL_VERSION_PATCH)

View File

@ -1,6 +1,6 @@
{
"name": "Embedded Template Library",
"version": "18.11.0",
"version": "18.11.1",
"authors": {
"name": "John Wellbelove",
"email": "john.wellbelove@etlcpp.com"

View File

@ -1,5 +1,5 @@
name=Embedded Template Library
version=18.11.0
version=18.11.1
author= John Wellbelove <john.wellbelove@etlcpp.com>
maintainer=John Wellbelove <john.wellbelove@etlcpp.com>
license=MIT

View File

@ -1,3 +1,7 @@
===============================================================================
18.11.1
Fix and optimise etl::list and etl::forward_list move constructors and assignment operators.
===============================================================================
18.11.0
Added etl::ibitset::span() member function to return a span of the underlying binary data.

View File

@ -215,7 +215,7 @@ namespace
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_copy_constructor)
TEST_FIXTURE(SetupFixture, test_copy_constructor_implicit_pool)
{
PoolNDC2 pool;
DataNDC data1(sorted_data.begin(), sorted_data.end(), pool);
@ -227,6 +227,71 @@ namespace
CHECK(std::equal(data2.begin(), data2.end(), other_data2.begin()));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_copy_constructor_explicit_pool)
{
PoolNDC2 pool;
DataNDC data1(sorted_data.begin(), sorted_data.end(), pool);
DataNDC data2(unsorted_data.begin(), unsorted_data.end(), pool);
DataNDC other_data1(data1, pool);
DataNDC other_data2(data2, pool);
CHECK(std::equal(data1.begin(), data1.end(), other_data1.begin()));
CHECK(std::equal(data2.begin(), data2.end(), other_data2.begin()));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_move_constructor_implicit_pool)
{
PoolNDC2 pool;
DataNDC data1(sorted_data.begin(), sorted_data.end(), pool);
DataNDC data2(unsorted_data.begin(), unsorted_data.end(), data1.get_pool());
DataNDC other_data1(std::move(data1));
DataNDC other_data2(std::move(data2));
CHECK_EQUAL(0U, data1.size());
CHECK(data1.empty());
CHECK_EQUAL(pool.max_size(), data1.max_size());
CHECK(data1.begin() == data1.end());
CHECK_EQUAL(0U, data2.size());
CHECK(data2.empty());
CHECK_EQUAL(pool.max_size(), data2.max_size());
CHECK(data2.begin() == data2.end());
CHECK_EQUAL(sorted_data.size(), other_data1.size());
CHECK_EQUAL(unsorted_data.size(), other_data2.size());
CHECK(std::equal(sorted_data.begin(), sorted_data.end(), other_data1.begin()));
CHECK(std::equal(unsorted_data.begin(), unsorted_data.end(), other_data2.begin()));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_move_constructor_explicit_pool)
{
PoolNDC2 pool;
DataNDC data1(sorted_data.begin(), sorted_data.end(), pool);
DataNDC data2(unsorted_data.begin(), unsorted_data.end(), data1.get_pool());
DataNDC other_data1(std::move(data1), pool);
DataNDC other_data2(std::move(data2), pool);
CHECK_EQUAL(0U, data1.size());
CHECK(data1.empty());
CHECK_EQUAL(pool.max_size(), data1.max_size());
CHECK(data1.begin() == data1.end());
CHECK_EQUAL(0U, data2.size());
CHECK(data2.empty());
CHECK_EQUAL(pool.max_size(), data2.max_size());
CHECK(data2.begin() == data2.end());
CHECK_EQUAL(sorted_data.size(), other_data1.size());
CHECK_EQUAL(unsorted_data.size(), other_data2.size());
CHECK(std::equal(sorted_data.begin(), sorted_data.end(), other_data1.begin()));
CHECK(std::equal(unsorted_data.begin(), unsorted_data.end(), other_data2.begin()));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_iterator)
{
@ -1177,6 +1242,75 @@ namespace
CHECK(are_equal);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_move_assignment)
{
PoolNDC4 pool;
DataNDC data1(sorted_data.begin(), sorted_data.end(), pool);
DataNDC data2(sorted_data.begin(), sorted_data.end(), data1.get_pool());
DataNDC other_data1(pool);
DataNDC other_data2(pool);
other_data1 = std::move(data1);
other_data2 = std::move(data2);
CHECK_EQUAL(0U, data1.size());
CHECK(data1.empty());
CHECK_EQUAL(pool.max_size(), data1.max_size());
CHECK(data1.begin() == data1.end());
CHECK_EQUAL(0U, data2.size());
CHECK(data2.empty());
CHECK_EQUAL(pool.max_size(), data2.max_size());
CHECK(data2.begin() == data2.end());
CHECK_EQUAL(sorted_data.size(), other_data1.size());
CHECK_EQUAL(sorted_data.size(), other_data2.size());
are_equal = std::equal(sorted_data.begin(), sorted_data.end(), other_data1.begin());
CHECK(are_equal);
are_equal = std::equal(sorted_data.begin(), sorted_data.end(), other_data2.begin());
CHECK(are_equal);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_move_assignment_through_interface)
{
PoolNDC4 pool;
DataNDC data1(sorted_data.begin(), sorted_data.end(), pool);
DataNDC data2(sorted_data.begin(), sorted_data.end(), data1.get_pool());
DataNDC other_data1(pool);
DataNDC other_data2(pool);
IDataNDC& idata1 = data1;
IDataNDC& idata2 = data2;
IDataNDC& iother_data1 = other_data1;
IDataNDC& iother_data2 = other_data2;
iother_data1 = std::move(idata1);
iother_data2 = std::move(idata2);
CHECK_EQUAL(0U, data1.size());
CHECK(data1.empty());
CHECK_EQUAL(pool.max_size(), data1.max_size());
CHECK(data1.begin() == data1.end());
CHECK_EQUAL(0U, data2.size());
CHECK(data2.empty());
CHECK_EQUAL(pool.max_size(), data2.max_size());
CHECK(data2.begin() == data2.end());
CHECK_EQUAL(sorted_data.size(), iother_data1.size());
CHECK_EQUAL(sorted_data.size(), iother_data2.size());
are_equal = std::equal(sorted_data.begin(), sorted_data.end(), iother_data1.begin());
CHECK(are_equal);
are_equal = std::equal(sorted_data.begin(), sorted_data.end(), iother_data2.begin());
CHECK(are_equal);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_assignment_interface)
{
@ -1199,7 +1333,7 @@ namespace
CompareDataNDC compare_data(sorted_data.begin(), sorted_data.end());
PoolNDC2 pool;
DataNDC data1(sorted_data.begin(), sorted_data.end(), pool);
DataNDC other_data(data1);
DataNDC other_data(data1, pool);
other_data = other_data;

View File

@ -264,7 +264,7 @@ namespace
#endif
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_copy_constructor)
TEST_FIXTURE(SetupFixture, test_copy_constructor_implicit_pool)
{
CompareData compare_data(half_data.begin(), half_data.end());
@ -287,6 +287,82 @@ namespace
CHECK_EQUAL(compare_data.size() - 2, other_data.size());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_copy_constructor_explicit_pool)
{
CompareData compare_data(half_data.begin(), half_data.end());
Pool pool;
DataNDC data(half_data.begin(), half_data.end(), pool);
DataNDC other_data(data, pool);
CHECK_EQUAL(data.size(), other_data.size());
CHECK(std::equal(data.begin(), data.end(), other_data.begin()));
CHECK(pool.full());
other_data.pop_front();
CHECK_EQUAL(compare_data.size(), data.size());
CHECK_EQUAL(compare_data.size() - 1, other_data.size());
other_data.pop_back();
CHECK_EQUAL(compare_data.size(), data.size());
CHECK_EQUAL(compare_data.size() - 2, other_data.size());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_move_constructor_implicit_pool)
{
Pool2 pool;
DataNDC data1(sorted_data.begin(), sorted_data.end(), pool);
DataNDC data2(unsorted_data.begin(), unsorted_data.end(), data1.get_pool());
DataNDC other_data1(std::move(data1));
DataNDC other_data2(std::move(data2));
CHECK_EQUAL(0U, data1.size());
CHECK(data1.empty());
CHECK_EQUAL(pool.max_size(), data1.max_size());
CHECK(data1.begin() == data1.end());
CHECK_EQUAL(0U, data2.size());
CHECK(data2.empty());
CHECK_EQUAL(pool.max_size(), data2.max_size());
CHECK(data2.begin() == data2.end());
CHECK_EQUAL(sorted_data.size(), other_data1.size());
CHECK_EQUAL(unsorted_data.size(), other_data2.size());
CHECK(std::equal(sorted_data.begin(), sorted_data.end(), other_data1.begin()));
CHECK(std::equal(unsorted_data.begin(), unsorted_data.end(), other_data2.begin()));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_move_constructor_explicit_pool)
{
Pool2 pool;
DataNDC data1(sorted_data.begin(), sorted_data.end(), pool);
DataNDC data2(unsorted_data.begin(), unsorted_data.end(), data1.get_pool());
DataNDC other_data1(std::move(data1), pool);
DataNDC other_data2(std::move(data2), pool);
CHECK_EQUAL(0U, data1.size());
CHECK(data1.empty());
CHECK_EQUAL(pool.max_size(), data1.max_size());
CHECK(data1.begin() == data1.end());
CHECK_EQUAL(0U, data2.size());
CHECK(data2.empty());
CHECK_EQUAL(pool.max_size(), data2.max_size());
CHECK(data2.begin() == data2.end());
CHECK_EQUAL(sorted_data.size(), other_data1.size());
CHECK_EQUAL(unsorted_data.size(), other_data2.size());
CHECK(std::equal(sorted_data.begin(), sorted_data.end(), other_data1.begin()));
CHECK(std::equal(unsorted_data.begin(), unsorted_data.end(), other_data2.begin()));
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_iterator)
{
@ -1222,6 +1298,38 @@ namespace
CHECK(pool.full());
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_move_assignment)
{
Pool4 pool;
DataNDC data1(sorted_data.begin(), sorted_data.end(), pool);
DataNDC data2(sorted_data.begin(), sorted_data.end(), data1.get_pool());
DataNDC other_data1(pool);
DataNDC other_data2(pool);
other_data1 = std::move(data1);
other_data2 = std::move(data2);
CHECK_EQUAL(0U, data1.size());
CHECK(data1.empty());
CHECK_EQUAL(pool.max_size(), data1.max_size());
CHECK(data1.begin() == data1.end());
CHECK_EQUAL(0U, data2.size());
CHECK(data2.empty());
CHECK_EQUAL(pool.max_size(), data2.max_size());
CHECK(data2.begin() == data2.end());
CHECK_EQUAL(sorted_data.size(), other_data1.size());
CHECK_EQUAL(sorted_data.size(), other_data2.size());
are_equal = std::equal(sorted_data.begin(), sorted_data.end(), other_data1.begin());
CHECK(are_equal);
are_equal = std::equal(sorted_data.begin(), sorted_data.end(), other_data2.begin());
CHECK(are_equal);
}
//*************************************************************************
TEST_FIXTURE(SetupFixture, test_assignment_interface)
{
@ -1727,7 +1835,7 @@ namespace
to = data.begin();
std::advance(to, 2);
DataNDC data2(data);
DataNDC data2(data, data.get_pool());
data.splice(to, data, begin, end);
CHECK_EQUAL(data.size(), data2.size());