Skip to content

Commit

Permalink
iox-eclipse-iceoryx#218 Initial implementation of unique_ptr with sto…
Browse files Browse the repository at this point in the history
…red custom deleter.

Signed-off-by: Ithier Jeff (CC-AD/EYF1) <[email protected]>
  • Loading branch information
orecham committed Aug 5, 2020
1 parent 5710c66 commit 2f5a499
Show file tree
Hide file tree
Showing 4 changed files with 269 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ class Publisher
///
void release(chunk_t&& chunk) const noexcept;

// To use this method, the user needs to know about the chunk concept.
// This means, the usage cannot be completely transparant (unless via copyAndPublish).
///
/// @brief send Publishes the chunk to the system.
/// @details Ownership of published chunks is automatically released.
Expand Down
106 changes: 106 additions & 0 deletions iceoryx_utils/include/iceoryx_utils/cxx/unique_ptr.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright (c) 2020 by Robert Bosch GmbH. 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.
// 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.

#ifndef IOX_UTILS_CXX_UNIQUE_PTR_HPP
#define IOX_UTILS_CXX_UNIQUE_PTR_HPP

#include "iceoryx_utils/cxx/function_ref.hpp"

namespace iox
{
namespace cxx
{

///
/// @todo document how it differs to STL
///
template<typename T>
class unique_ptr{
public:

using ptr_t = T*;

///
/// @brief unique_ptr Creates an empty unique ptr that owns nothing. Can be passed ownership later.
///
unique_ptr(function_ref<void(ptr_t const)> deleter) noexcept;

///
/// @brief unique_ptr Creates a unique pointer.
/// @details A delete must always be provided as no heap is used. The unique_ptr needs to know how to delete
/// the object when the reference is out of scope.
/// @param ptr The raw pointer to the object to take ownership of.
/// @param deleter The deleter function for cleaning up the object.
///
unique_ptr(ptr_t ptr, const function_ref<void(ptr_t const)> deleter) noexcept;

unique_ptr(void* allocation, const function_ref<void(ptr_t const)> deleter) noexcept;

// Not copy-able to ensure uniqueness.
unique_ptr(const unique_ptr& other) = delete;
unique_ptr& operator=(const unique_ptr&) = delete;

// These might need to be specialized.
unique_ptr(unique_ptr&& rhs) = default;
unique_ptr& operator=(unique_ptr&& rhs) = default;

///
/// Automatically deletes the owned object on destruction.
///
~unique_ptr() noexcept;

/// Dereference the stored pointer.
T operator*() noexcept;

/// Return the stored pointer.
ptr_t operator->() noexcept;

///
/// @brief get Retrieve the underlying raw pointer.
/// @details The unique_ptr retains ownership, therefore the "borrowed" pointer must not be deleted.
/// @return Pointer to managed object or nullptr if none owned.
///
ptr_t get() noexcept;

///
/// @brief release Releases ownership of the underlying pointer.
/// @return Pointer to the managed object or nullptr if none owned.
///
ptr_t release() noexcept;

///
/// @brief reset Reset the unique_ptr instance's owned object to the one given.
/// @details Any previously owned objects will be deleted.
/// @param ptr Pointer to object to take ownership on.
///
void reset(ptr_t ptr) noexcept;

///
/// @brief swap Swaps object ownership with another unique_ptr.
/// @param other The unique_ptr with which to swap owned objects.
///
void swap(unique_ptr& other) noexcept;

private:
ptr_t m_ptr = nullptr;
function_ref<void(ptr_t const)> m_deleter;
};


} // namespace cxx
} // namespace iox

#include "iceoryx_utils/internal/cxx/unique_ptr.inl"

#endif // IOX_UTILS_CXX_UNIQUE_PTR_HPP
84 changes: 84 additions & 0 deletions iceoryx_utils/include/iceoryx_utils/internal/cxx/unique_ptr.inl
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@

#ifndef IOX_UTILS_CXX_UNIQUE_PTR_INL
#define IOX_UTILS_CXX_UNIQUE_PTR_INL

#include "iceoryx_utils/cxx/unique_ptr.hpp"

namespace iox
{
namespace cxx
{

template<typename T>
unique_ptr<T>::unique_ptr(const function_ref<void(T* const)> deleter) noexcept : m_deleter(deleter)
{}

template<typename T>
unique_ptr<T>::unique_ptr(ptr_t ptr, const function_ref<void(T* const)> deleter) noexcept : m_ptr(ptr), m_deleter(deleter)
{}

template<typename T>
unique_ptr<T>::unique_ptr(void* allocation, const function_ref<void(ptr_t const)> deleter) noexcept
: m_ptr(reinterpret_cast<T*>(allocation)), m_deleter(deleter)
{}

template<typename T>
unique_ptr<T>::~unique_ptr() noexcept
{
m_deleter(m_ptr);
}

/// Dereference the stored pointer.
template<typename T>
T unique_ptr<T>::operator*() noexcept
{
return *get();
}

/// Return the stored pointer.
template<typename T>
T* unique_ptr<T>::operator->() noexcept
{
return get();
}


template<typename T>
T* unique_ptr<T>::get() noexcept
{
return m_ptr;
}

template<typename T>
T* unique_ptr<T>::release() noexcept
{
auto ptr = m_ptr;
m_ptr = nullptr;
return ptr;
}

template<typename T>
void unique_ptr<T>::reset(T* ptr) noexcept
{
if(m_ptr)
{
m_deleter(m_ptr);
}
m_ptr = ptr;
}

template<typename T>
void unique_ptr<T>::swap(unique_ptr<T>& other) noexcept
{
// Release pointers from both instances.
auto thisPtr = release();
auto otherPtr = other.release();
// Set new pointers on both instances.
reset(otherPtr);
other.reset(release());
}

} // namespace iox
} // namespace popo

#endif // IOX_UTILS_CXX_UNIQUE_PTR_INL
79 changes: 79 additions & 0 deletions iceoryx_utils/test/moduletests/test_cxx_unique_ptr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (c) 2019 by Robert Bosch GmbH. 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.
// 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.

#include "iceoryx_utils/cxx/unique_ptr.hpp"
#include "test.hpp"

#include <iostream>

using namespace ::testing;

struct Position {
double_t x = 0.0;
double_t y = 0.0;
double_t z = 0.0;
};

class UniquePtrTest : public Test {

public:
UniquePtrTest()
{

}

void SetUp()
{
}

void TearDown()
{
}

};

TEST_F(UniquePtrTest, CanBeConstructedWithUndefinedBlob)
{
auto deleter = [](Position* const p){delete p;};
uint8_t* buf = new uint8_t[sizeof(Position)];
auto ptr = iox::cxx::unique_ptr<Position>(buf, deleter);

ptr->x = 10.0;
ptr->y = 77.77;
ptr->z = 50.50;

EXPECT_EQ(10.0, ptr->x);
EXPECT_EQ(77.77, ptr->y);
EXPECT_EQ(50.50, ptr->z);

}

TEST_F(UniquePtrTest, CanBeResetToPointToUndefinedBlob)
{

auto deleter = [](Position* const p){delete p;};
auto ptr = iox::cxx::unique_ptr<Position>(deleter);

uint8_t* buf = new uint8_t[sizeof(Position)];
ptr.reset(reinterpret_cast<Position*>(buf));

ptr->x = 10.0;
ptr->y = 77.77;
ptr->z = 50.50;

EXPECT_EQ(10.0, ptr->x);
EXPECT_EQ(77.77, ptr->y);
EXPECT_EQ(50.50, ptr->z);

}

0 comments on commit 2f5a499

Please sign in to comment.