Skip to content

Commit

Permalink
iox-eclipse-iceoryx#605 fix docu and rename atomic relocatable pointer
Browse files Browse the repository at this point in the history
Signed-off-by: Marika Lehmann <[email protected]>
  • Loading branch information
FerdinandSpitzschnueffler committed Mar 19, 2021
1 parent dd1689c commit c3e1ee8
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 36 deletions.
32 changes: 16 additions & 16 deletions doc/design/relocatable_pointer.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ even to the shared memory), i.e. the pointer is invalid. In this case, different
relocatable pointers must be used. Depending on the shared memory setup and the relationship between pointer and pointee,
there are different use cases which we need to cover.

Both relative_ptr<T> and relocatable_ptr<T> are template pointer classes that try to retain much of the normal pointer
Both RelativePointer<T> and RelocatablePointer<T> are template pointer classes that try to retain much of the normal pointer
syntax where possible while still being valid across address space boundaries. This means that operations like
assignment, dereferencing, comparison and so on work similar to raw pointers. They do not possess reference counting
semantics in this implementation, but extensions for this functionality are possible.
Expand Down Expand Up @@ -44,7 +44,7 @@ This is why storing a raw pointer to X will not be sufficient, the value c1 of p
However, storing the difference between the location of p and X will work since it is an invariant in both address
spaces.

Thus, instead of using a raw pointer p, we just use a relocatable pointer relocatable_ptr<T> pointing to X. This pointer
Thus, instead of using a raw pointer p, we just use a relocatable pointer RelocatablePointer<T> pointing to X. This pointer
can then be dereferenced in both address spaces and will point to X.

Note that if we only use relocatable pointers in this way in complex data structures that rely on pointers (such as
Expand All @@ -60,16 +60,16 @@ segment* (e.g. as members of objects that reside in this segment or via emplacem
segment).

default construct a logical nullptr
+ `relocatable_ptr<T> p;`
+ `RelocatablePointer<T> p;`

construct relocatable pointing to X
+ `relocatable_ptr<T> p(&X);`
+ `RelocatablePointer<T> p(&X);`

assign relocatable to point to X
+ `p = &X;`

### Operations
Most operations for raw pointers also work for relocatable pointers. In particular, a relocatable_ptr<T> is compatible
Most operations for raw pointers also work for relocatable pointers. In particular, a RelocatablePointer<T> is compatible
with a raw pointer T* in many cases, such as assignment, to provide seamless integration and convenient syntax.

comparison with raw pointers
Expand Down Expand Up @@ -151,19 +151,19 @@ Assume we have an object X of type T in shared memory. Then we can construct rel
registered segments*.

default construct a logical nullptr
+ `relative_ptr<T> rp;`
+ `RelativePointer<T> rp;`

construct relative pointer pointing to X (provided the segment containing X was registered)
+ `relative_ptr<T> rp(&X);`
+ `RelativePointer<T> rp(&X);`

assign relative pointer to point to X
+ `rp = &X;`

copy construction
+ `relative_ptr<T> rp2(rp);`
+ `RelativePointer<T> rp2(rp);`

copy assignment
+ `relative_ptr<T> rp2 = rp;`
+ `RelativePointer<T> rp2 = rp;`

### Operations

Expand Down Expand Up @@ -197,19 +197,19 @@ the operations incur slightly more overhead compared to relocatable pointers.

## Atomic usage

There is a technical problem using both relocatable_ptr and relative_ptr as a type in a std::atomic. This is essentially
There is a technical problem using both RelocatablePointer and RelativePointer as a type in a std::atomic. This is essentially
impossible as an atomic requires its type to be copyable/movable (to be loaded) but on the other hand, this copy
constructor must be trivial, i.e. performable with a shallow memcpy. Therefore, the types used in atomic cannot implement
custom copy/move. This is not possible for relocatable_ptr and relative_ptr as both require operations performed
custom copy/move. This is not possible for RelocatablePointer and RelativePointer as both require operations performed
during copying, which cannot be done by a simple shallow copy.

To support the use case of an atomic relocatable pointer, the template atomic_relocatable_ptr<T> is provided. It is a
basic version of a relocatable_ptr, which lacks some of its move functionality and other operations. However, its
existing operations behave like relocatable_ptr but in an atomic way (but also incur additional overhead caused by
To support the use case of an atomic relocatable pointer, the template AtomicRelocatablePointer<T> is provided. It is a
basic version of a RelocatablePointer, which lacks some of its move functionality and other operations. However, its
existing operations behave like RelocatablePointer but in an atomic way (but also incur additional overhead caused by
atomic loads and stores). Therefore, this object can be used concurrently by multiple threads, in contrast to
relative_ptr and relocatable_ptr. This atomic version also utilizes lock free atomic operations internally (when
RelativePointer and RelocatablePointer. This atomic version also utilizes lock free atomic operations internally (when
available on the target architecture) as the data to be stored is just a 64 bit word.

Note that this cannot be done as easily for relative_ptr as it requires more than 64 bit to store its internal
Note that this cannot be done as easily for RelativePointer as it requires more than 64 bit to store its internal
information. A construction where atomicity is guaranteed via locking could be provided in the future.

Original file line number Diff line number Diff line change
Expand Up @@ -31,28 +31,28 @@ namespace rp
/// internally used offset must be an invariant different across adress spaces. Rationale: the default
/// RelocatablePointer cannot be used in an atomic since the copy ctor is nontrivial.
template <typename T>
class atomic_relocatable_ptr
class AtomicRelocatablePointer
{
public:
using offset_t = std::ptrdiff_t;
static constexpr offset_t NULL_POINTER_OFFSET = std::numeric_limits<offset_t>::max();

/// @brief creates an atomic_relocatable_ptr pointing to the same pointee as ptr
/// @brief creates an AtomicRelocatablePointer pointing to the same pointee as ptr
/// @param[in] ptr the pointer whose pointee shall be the same for this
atomic_relocatable_ptr(const T* ptr = nullptr) noexcept;
AtomicRelocatablePointer(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;
atomic_relocatable_ptr& operator=(const atomic_relocatable_ptr& other) = delete;
atomic_relocatable_ptr(atomic_relocatable_ptr&& other) = delete;
atomic_relocatable_ptr& operator=(atomic_relocatable_ptr&& other) = delete;
AtomicRelocatablePointer(const AtomicRelocatablePointer&) = delete;
AtomicRelocatablePointer& operator=(const AtomicRelocatablePointer& other) = delete;
AtomicRelocatablePointer(AtomicRelocatablePointer&& other) = delete;
AtomicRelocatablePointer& operator=(AtomicRelocatablePointer&& other) = delete;

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

/// @brief assign atomic_relocatable_ptr to point to the same pointee as ptr
/// @brief assign AtomicRelocatablePointer to point to the same pointee as ptr
/// @param[in] ptr the pointer whose pointee shall be the same for this
/// @return reference to self
atomic_relocatable_ptr& operator=(const T* ptr) noexcept;
AtomicRelocatablePointer& operator=(const T* ptr) noexcept;

/// @brief access to the underlying object in shared memory
/// @return a pointer to the underlying object
Expand All @@ -62,7 +62,7 @@ class atomic_relocatable_ptr
/// @return a reference to the pointee
T& operator*() const noexcept;

/// @brief converts the atomic_relocatable_ptr to a pointer of type of the underlying object
/// @brief converts the AtomicRelocatablePointer to a pointer of type of the underlying object
/// @return a pointer of type T pointing to the underlying object
operator T*() const noexcept;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,39 +25,39 @@ namespace iox
namespace rp
{
template <typename T>
inline atomic_relocatable_ptr<T>::atomic_relocatable_ptr(const T* ptr) noexcept
inline AtomicRelocatablePointer<T>::AtomicRelocatablePointer(const T* ptr) noexcept
: m_offset(computeOffset(ptr))
{
}

template <typename T>
inline atomic_relocatable_ptr<T>& atomic_relocatable_ptr<T>::operator=(const T* ptr) noexcept
inline AtomicRelocatablePointer<T>& AtomicRelocatablePointer<T>::operator=(const T* ptr) noexcept
{
m_offset.store(computeOffset(ptr), std::memory_order_relaxed);
return *this;
}

template <typename T>
inline T* atomic_relocatable_ptr<T>::operator->() const noexcept
inline T* AtomicRelocatablePointer<T>::operator->() const noexcept
{
return computeRawPtr();
}

template <typename T>
inline T& atomic_relocatable_ptr<T>::operator*() const noexcept
inline T& AtomicRelocatablePointer<T>::operator*() const noexcept
{
return *computeRawPtr();
}


template <typename T>
inline atomic_relocatable_ptr<T>::operator T*() const noexcept
inline AtomicRelocatablePointer<T>::operator T*() const noexcept
{
return computeRawPtr();
}

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

template <typename T>
inline typename atomic_relocatable_ptr<T>::offset_t
atomic_relocatable_ptr<T>::computeOffset(const void* ptr) const noexcept
inline typename AtomicRelocatablePointer<T>::offset_t
AtomicRelocatablePointer<T>::computeOffset(const void* ptr) const noexcept
{
if (ptr == nullptr)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ class PointerRepository
/// @attention the relative pointers corresponding to this id become unsafe to use
bool unregisterPtr(id_t id) noexcept;

/// @brief unregisters all ids and also invalidates all relative pointers
/// @brief unregisters all ids
/// @attention the relative pointers corresponding to this id become unsafe to use
void unregisterAll() noexcept;

/// @brief gets the base pointer, i.e. the starting address, associated with id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class Foo
};

template <typename T>
using Ptr = iox::rp::atomic_relocatable_ptr<T>;
using Ptr = iox::rp::AtomicRelocatablePointer<T>;

class AtomicRelocatablePointer_test : public Test
{
Expand Down

0 comments on commit c3e1ee8

Please sign in to comment.