Skip to content

Commit

Permalink
Merge pull request #2069 from Dennis40816/iox-2052-fixedpositionconta…
Browse files Browse the repository at this point in the history
…iner-copymove-func-impl

iox-#2052 Implement move/copy constructor and assignment for `FixedPositionContainer`
  • Loading branch information
elBoberido authored Nov 13, 2023
2 parents 30f8dca + 5ee7097 commit 7995b3c
Show file tree
Hide file tree
Showing 5 changed files with 1,831 additions and 15 deletions.
2 changes: 2 additions & 0 deletions doc/website/release-notes/iceoryx-unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@
- LockFreeQueue fails to support move-only types [\#2067](https://github.com/eclipse-iceoryx/iceoryx/issues/2067)
- Fix musl libc compile (missing sys/stat.h include in mqueue.h for mode_t definition) [\#2072](https://github.com/eclipse-iceoryx/iceoryx/issues/2072)
- cxx::Expects macro conflicts with Microsoft GSL Expects macro [#2080](https://github.com/eclipse-iceoryx/iceoryx/issues/2080)
- Implement move/copy constructor and assignment for `FixedPositionContainer` [#2052](https://github.com/eclipse-iceoryx/iceoryx/issues/2052)


**Refactoring:**

Expand Down
134 changes: 134 additions & 0 deletions iceoryx_dust/container/include/iox/detail/fixed_position_container.inl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2023 by Mathias Kraus <[email protected]>. All rights reserved.
// Copyright (c) 2023 by Dennis Liu <[email protected]>. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -18,6 +19,9 @@
#define IOX_DUST_CONTAINER_DETAIL_FIXED_POSITION_CONTAINER_INL

#include "iox/fixed_position_container.hpp"
#if __cplusplus < 201703L
#include "iox/detail/fixed_position_container_helper.hpp"
#endif

namespace iox
{
Expand Down Expand Up @@ -51,6 +55,136 @@ inline FixedPositionContainer<T, CAPACITY>::~FixedPositionContainer() noexcept
}
}

template <typename T, uint64_t CAPACITY>
inline FixedPositionContainer<T, CAPACITY>::FixedPositionContainer(const FixedPositionContainer& rhs) noexcept
{
for (IndexType i = 0; i < CAPACITY; ++i)
{
m_status[i] = SlotStatus::FREE;
}

*this = rhs;
}

template <typename T, uint64_t CAPACITY>
inline FixedPositionContainer<T, CAPACITY>::FixedPositionContainer(FixedPositionContainer&& rhs) noexcept
{
for (IndexType i = 0; i < CAPACITY; ++i)
{
m_status[i] = SlotStatus::FREE;
}

*this = std::move(rhs);
}

template <typename T, uint64_t CAPACITY>
inline FixedPositionContainer<T, CAPACITY>&
FixedPositionContainer<T, CAPACITY>::operator=(const FixedPositionContainer& rhs) noexcept
{
if (this != &rhs)
{
copy_and_move_impl(rhs);
}
return *this;
}

template <typename T, uint64_t CAPACITY>
inline FixedPositionContainer<T, CAPACITY>&
FixedPositionContainer<T, CAPACITY>::operator=(FixedPositionContainer&& rhs) noexcept
{
if (this != &rhs)
{
copy_and_move_impl(std::move(rhs));

// clear rhs
rhs.clear();
}
return *this;
}

template <typename T, uint64_t CAPACITY>
template <typename RhsType>
inline void FixedPositionContainer<T, CAPACITY>::copy_and_move_impl(RhsType&& rhs) noexcept
{
// we already make sure rhs is always passed by std::move() for move case, therefore
// the result of "decltype(rhs)" is same as "decltype(std::forward<RhsType>(rhs))"
static_assert(std::is_rvalue_reference<decltype(rhs)>::value
|| (std::is_lvalue_reference<decltype(rhs)>::value
&& std::is_const<std::remove_reference_t<decltype(rhs)>>::value),
"RhsType must be const lvalue reference or rvalue reference");

constexpr bool is_move = std::is_rvalue_reference<decltype(rhs)>::value;

IndexType i{Index::FIRST};
auto rhs_it = (std::forward<RhsType>(rhs)).begin();

// transfer src data to destination
for (; rhs_it.to_index() != Index::INVALID; ++i, ++rhs_it)
{
if (m_status[i] == SlotStatus::USED)
{
#if __cplusplus >= 201703L
if constexpr (is_move)
{
m_data[i] = std::move(*rhs_it);
}
else
{
m_data[i] = *rhs_it;
}
#else
// We introduce a helper struct primarily due to the test case
// e1cc7c9f-c1b5-4047-811b-004302af5c00. It demands compile-time if-else branching
// for classes that are either non-copyable or non-moveable.
// Note: With C++17's 'if constexpr', the need for these helper structs can be eliminated.
detail::AssignmentHelper<is_move>::assign(m_data[i], detail::MoveHelper<is_move>::move_or_copy(rhs_it));
#endif
}
// use ctor to avoid UB for non-initialized free slots
else
{
#if __cplusplus >= 201703L
if constexpr (is_move)
{
new (&m_data[i]) T(std::move(*rhs_it));
}
else
{
new (&m_data[i]) T(*rhs_it);
}
#else
// Same as above
detail::CtorHelper<is_move>::construct(m_data[i], detail::MoveHelper<is_move>::move_or_copy(rhs_it));
#endif
}
m_status[i] = SlotStatus::USED;
m_next[i] = static_cast<IndexType>(i + 1U);
}

for (; i < CAPACITY; ++i)
{
if (m_status[i] == SlotStatus::USED)
{
m_data[i].~T();
}

m_status[i] = SlotStatus::FREE;

IndexType next = static_cast<IndexType>(i + 1U);
m_next[i] = next;
}

m_next[Index::LAST] = Index::INVALID;
if (!rhs.empty())
{
m_next[rhs.m_size - 1] = Index::INVALID;
}

m_begin_free = static_cast<IndexType>(rhs.m_size);
m_begin_used = rhs.empty() ? Index::INVALID : Index::FIRST;
m_size = rhs.m_size;
}

template <typename T, uint64_t CAPACITY>
inline void FixedPositionContainer<T, CAPACITY>::clear() noexcept
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright (c) 2023 by Dennis Liu <[email protected]>. All rights reserved. reserved.
//
// 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.
//
// SPDX-License-Identifier: Apache-2.0

#ifndef IOX_DUST_CONTAINER_DETAIL_FIXED_POSITION_CONTAINER_HELPER_HPP
#define IOX_DUST_CONTAINER_DETAIL_FIXED_POSITION_CONTAINER_HELPER_HPP

#include <utility>

namespace iox
{
namespace detail
{
template <bool IsMove>
struct AssignmentHelper;

template <>
struct AssignmentHelper<true>
{
template <typename T>
static void assign(T& dest, T&& src)
{
dest = std::forward<T>(src);
}
};

template <>
struct AssignmentHelper<false>
{
template <typename T>
static void assign(T& dest, const T& src)
{
dest = src;
}
};

template <bool IsMove>
struct CtorHelper;

template <>
struct CtorHelper<true>
{
template <typename T>
static void construct(T& dest, T&& src)
{
new (&dest) T(std::forward<T>(src));
}
};

template <>
struct CtorHelper<false>
{
template <typename T>
static void construct(T& dest, const T& src)
{
new (&dest) T(src);
}
};

template <bool IsMove>
struct MoveHelper;

template <>
struct MoveHelper<true>
{
template <typename Iterator>
static auto move_or_copy(Iterator& it) -> decltype(std::move(*it))
{
return std::move(*it);
}
};

template <>
struct MoveHelper<false>
{
template <typename Iterator>
static auto move_or_copy(Iterator& it) -> decltype(*it)
{
return *it;
}
};

#endif
}
}
12 changes: 8 additions & 4 deletions iceoryx_dust/container/include/iox/fixed_position_container.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ class FixedPositionContainer final
FixedPositionContainer() noexcept;
~FixedPositionContainer() noexcept;

FixedPositionContainer(const FixedPositionContainer&) noexcept = delete;
FixedPositionContainer(FixedPositionContainer&&) noexcept = delete;
FixedPositionContainer(const FixedPositionContainer&) noexcept;
FixedPositionContainer(FixedPositionContainer&&) noexcept;

FixedPositionContainer& operator=(const FixedPositionContainer&) noexcept = delete;
FixedPositionContainer& operator=(FixedPositionContainer&&) noexcept = delete;
FixedPositionContainer& operator=(const FixedPositionContainer&) noexcept;
FixedPositionContainer& operator=(FixedPositionContainer&&) noexcept;

/// @brief Clears the container and calls the destructor on all contained elements
void clear() noexcept;
Expand Down Expand Up @@ -317,6 +317,10 @@ class FixedPositionContainer final
IndexType m_index;
};

private:
template <typename RhsType>
void copy_and_move_impl(RhsType&& rhs) noexcept;

private:
UninitializedArray<T, CAPACITY> m_data;
UninitializedArray<SlotStatus, CAPACITY> m_status;
Expand Down
Loading

0 comments on commit 7995b3c

Please sign in to comment.