Skip to content

Commit

Permalink
iox-eclipse-iceoryx#605 add noexcept, const, replace size_t, use uint…
Browse files Browse the repository at this point in the history
…ptr_t

Signed-off-by: Marika Lehmann <[email protected]>
  • Loading branch information
FerdinandSpitzschnueffler committed Mar 11, 2021
1 parent 8dd4313 commit 5200fc7
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 136 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

#ifndef IOX_UTILS_RELOCATABLE_POINTER_ATOMIC_RELOCATABLE_PTR_HPP
#define IOX_UTILS_RELOCATABLE_POINTER_ATOMIC_RELOCATABLE_PTR_HPP

Expand All @@ -21,7 +22,7 @@

namespace iox
{
///@brief minimalistic relocatable pointer that can be written and read atomically
/// @brief minimalistic relocatable pointer that can be written and read atomically
/// and can be stored safely in shared memory.
/// As the basic relocatable_ptr, it must point to something in the same shared memory segment as itself
/// since the internally used offset must be an invariant different across adress spaces.
Expand All @@ -33,7 +34,7 @@ class atomic_relocatable_ptr
using offset_t = std::ptrdiff_t;
static constexpr offset_t NULL_POINTER_OFFSET = std::numeric_limits<offset_t>::max();

atomic_relocatable_ptr(const T* ptr = nullptr);
atomic_relocatable_ptr(const T* ptr = nullptr) noexcept;

///@todo: can be implemented when needed, note that the offset must be recomputed during the move/copy
atomic_relocatable_ptr(const atomic_relocatable_ptr&) = delete;
Expand All @@ -42,8 +43,7 @@ class atomic_relocatable_ptr
atomic_relocatable_ptr(atomic_relocatable_ptr&& other) = delete;
atomic_relocatable_ptr& operator=(atomic_relocatable_ptr&& other) = delete;

// minimal set of required operators, can be extended later

/// @note minimal set of required operators, can be extended later
atomic_relocatable_ptr& operator=(const T* ptr) noexcept;

T* operator->() const noexcept;
Expand All @@ -55,9 +55,9 @@ class atomic_relocatable_ptr
private:
std::atomic<offset_t> m_offset{NULL_POINTER_OFFSET};

inline T* computeRawPtr() const;
inline T* computeRawPtr() const noexcept;

inline offset_t computeOffset(const void* ptr) const;
inline offset_t computeOffset(const void* ptr) const noexcept;
};

} // namespace iox
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

#ifndef IOX_UTILS_RELOCATABLE_POINTER_ATOMIC_RELOCATABLE_PTR_INL
#define IOX_UTILS_RELOCATABLE_POINTER_ATOMIC_RELOCATABLE_PTR_INL

Expand All @@ -21,7 +22,7 @@
namespace iox
{
template <typename T>
inline atomic_relocatable_ptr<T>::atomic_relocatable_ptr(const T* ptr)
inline atomic_relocatable_ptr<T>::atomic_relocatable_ptr(const T* ptr) noexcept
: m_offset(computeOffset(ptr))
{
}
Expand Down Expand Up @@ -53,7 +54,7 @@ inline atomic_relocatable_ptr<T>::operator T*() const noexcept
}

template <typename T>
inline T* atomic_relocatable_ptr<T>::computeRawPtr() const
inline T* atomic_relocatable_ptr<T>::computeRawPtr() const noexcept
{
auto offset = m_offset.load(std::memory_order_relaxed);
if (offset == NULL_POINTER_OFFSET)
Expand All @@ -65,7 +66,8 @@ inline T* atomic_relocatable_ptr<T>::computeRawPtr() const
}

template <typename T>
inline typename atomic_relocatable_ptr<T>::offset_t atomic_relocatable_ptr<T>::computeOffset(const void* ptr) const
inline typename atomic_relocatable_ptr<T>::offset_t
atomic_relocatable_ptr<T>::computeOffset(const void* ptr) const noexcept
{
if (ptr == nullptr)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

#ifndef IOX_UTILS_RELOCATABLE_POINTER_POINTER_REPOSITORY_HPP
#define IOX_UTILS_RELOCATABLE_POINTER_POINTER_REPOSITORY_HPP

Expand All @@ -23,12 +24,12 @@

namespace iox
{
///@brief Allows registration of memory segments with their start pointers and size.
/// @brief Allows registration of memory segments with their start pointers and size.
/// This class is used to resolve relative pointers in the corresponding address space of the application.
/// Up to CAPACITY segments can be registered with MIN_ID = 1 to MAX_ID = CAPACITY - 1
/// id 0 is reserved and allows relative pointers to behave like normal pointers
/// (which is equivalent to measure the offset relative to 0).
template <typename id_t, typename ptr_t, size_t CAPACITY = 10000>
template <typename id_t, typename ptr_t, uint64_t CAPACITY = 10000U>
class PointerRepository
{
private:
Expand All @@ -38,21 +39,21 @@ class PointerRepository
ptr_t endPtr{nullptr};
};

static constexpr size_t MAX_ID = CAPACITY - 1u;
static constexpr size_t MIN_ID = 1u;
// remark: 0 is a special purpose id and reserved
// id 0 is reserved to interpret the offset just as a raw pointer,
// i.e. its corresponding base ptr is 0
/// @note 0 is a special purpose id and reserved
/// id 0 is reserved to interpret the offset just as a raw pointer,
/// i.e. its corresponding base ptr is 0
static constexpr size_t MIN_ID = 1U;
static constexpr size_t MAX_ID = CAPACITY - 1U;

public:
static constexpr id_t INVALID_ID = std::numeric_limits<id_t>::max();

PointerRepository()
PointerRepository() noexcept
: m_info(CAPACITY)
{
}

bool registerPtr(id_t id, ptr_t ptr, uint64_t size)
bool registerPtr(const id_t id, const ptr_t ptr, const uint64_t size) noexcept
{
if (id > MAX_ID)
{
Expand All @@ -61,7 +62,7 @@ class PointerRepository
if (m_info[id].basePtr == nullptr)
{
m_info[id].basePtr = ptr;
m_info[id].endPtr = reinterpret_cast<ptr_t>(reinterpret_cast<uint64_t>(ptr) + size - 1u);
m_info[id].endPtr = reinterpret_cast<ptr_t>(reinterpret_cast<uintptr_t>(ptr) + size - 1U);
if (id > m_maxRegistered)
{
m_maxRegistered = id;
Expand All @@ -71,14 +72,14 @@ class PointerRepository
return false;
}

id_t registerPtr(const ptr_t ptr, uint64_t size = 0u)
id_t registerPtr(const ptr_t ptr, const uint64_t size = 0U) noexcept
{
for (id_t id = 1u; id <= MAX_ID; ++id)
for (id_t id = 1U; id <= MAX_ID; ++id)
{
if (m_info[id].basePtr == nullptr)
{
m_info[id].basePtr = ptr;
m_info[id].endPtr = reinterpret_cast<ptr_t>(reinterpret_cast<uint64_t>(ptr) + size - 1u);
m_info[id].endPtr = reinterpret_cast<ptr_t>(reinterpret_cast<uintptr_t>(ptr) + size - 1U);
if (id > m_maxRegistered)
{
m_maxRegistered = id;
Expand All @@ -90,70 +91,71 @@ class PointerRepository
return INVALID_ID;
}

bool unregisterPtr(id_t id)
bool unregisterPtr(const id_t id) noexcept
{
if (id <= MAX_ID && id >= MIN_ID)
{
if (m_info[id].basePtr != nullptr)
{
m_info[id].basePtr = nullptr;

// do not search for next lower registered index but we could do it here
/// @note do not search for next lower registered index but we could do it here
return true;
}
}

return false;
}

void unregisterAll()
void unregisterAll() noexcept
{
for (auto& info : m_info)
{
info.basePtr = nullptr;
}
m_maxRegistered = 0u;
m_maxRegistered = 0U;
}

ptr_t getBasePtr(id_t id)
ptr_t getBasePtr(const id_t id) const noexcept
{
if (id <= MAX_ID && id >= MIN_ID)
{
return m_info[id].basePtr;
}

// for id 0 nullptr is returned, meaning we will later interpret a relative pointer
// by casting the offset into a pointer (i.e. we measure relative to 0)
/// @note for id 0 nullptr is returned, meaning we will later interpret a relative pointer
/// by casting the offset into a pointer (i.e. we measure relative to 0)

return nullptr; // we cannot distinguish between not registered and nullptr registered, but we do not need to
/// @note we cannot distinguish between not registered and nullptr registered, but we do not need to
return nullptr;
}

id_t searchId(ptr_t ptr)
id_t searchId(const ptr_t ptr) const noexcept
{
for (id_t id = 1u; id <= m_maxRegistered; ++id)
for (id_t id = 1U; id <= m_maxRegistered; ++id)
{
// return first id where the ptr is in the corresponding interval
if (ptr >= m_info[id].basePtr && ptr <= m_info[id].endPtr)
{
return id;
}
}
// implicitly interpret the pointer as a regular pointer if not found
// by setting id to 0
// rationale: test cases work without registered shared memory and require
// this at the moment to avoid fundamental changes
return 0u;
/// @note implicitly interpret the pointer as a regular pointer if not found
/// by setting id to 0
/// rationale: test cases work without registered shared memory and require
/// this at the moment to avoid fundamental changes
return 0U;
// return INVALID_ID;
}

bool isValid(id_t id)
bool isValid(const id_t id) const noexcept
{
return id != INVALID_ID;
}

void print()
void print() const noexcept
{
for (id_t id = 0; id < m_info.size(); ++id)
for (id_t id = 0U; id < m_info.size(); ++id)
{
auto ptr = m_info[id].basePtr;
if (ptr != nullptr)
Expand All @@ -164,14 +166,14 @@ class PointerRepository
}

private:
///@ todo: if required protect vector against concurrent modification
/// @todo: if required protect vector against concurrent modification
// whether this is required depends on the use case, we currently do not need it
// we control the ids, so if they are consecutive we only need a vector/array to get the address
// this variable exists once per application using relative pointers,
// and each needs to initialize it via register calls above

iox::cxx::vector<Info, CAPACITY> m_info;
uint64_t m_maxRegistered{0u};
uint64_t m_maxRegistered{0U};
};

} // namespace iox
Expand Down
Loading

0 comments on commit 5200fc7

Please sign in to comment.