diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c4e938284..4c480ce3b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - Cpptoml can be provided by an external source[\#951](https://github.com/eclipse-iceoryx/iceoryx/issues/) - Extend cxx::optional constructor for in place construction so that copy/move for values inside the optional even could be deleted[\#967](https://github.com/eclipse-iceoryx/iceoryx/issues/967) - Add templated `from`/`into` free functions to formalize conversions from enums and other types [#992](https://github.com/eclipse-iceoryx/iceoryx/issues/992) +- UniqueId class for unique IDs within a process [#1010](https://github.com/eclipse-iceoryx/iceoryx/issues/1010) **Bugfixes:** diff --git a/iceoryx_hoofs/CMakeLists.txt b/iceoryx_hoofs/CMakeLists.txt index 81f3c872f7..0dc0fef10d 100644 --- a/iceoryx_hoofs/CMakeLists.txt +++ b/iceoryx_hoofs/CMakeLists.txt @@ -144,6 +144,7 @@ add_library(iceoryx_hoofs source/cxx/deadline_timer.cpp source/cxx/helplets.cpp source/cxx/generic_raii.cpp + source/cxx/unique_id.cpp source/error_handling/error_handling.cpp source/file_reader/file_reader.cpp source/log/logcommon.cpp diff --git a/iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/unique_id.hpp b/iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/unique_id.hpp new file mode 100644 index 0000000000..e443c8daf0 --- /dev/null +++ b/iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/unique_id.hpp @@ -0,0 +1,54 @@ +// Copyright (c) 2022 by Apex.AI Inc. 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. +// +// SPDX-License-Identifier: Apache-2.0 + +#ifndef IOX_HOOFS_CXX_UNIQUE_ID_HPP +#define IOX_HOOFS_CXX_UNIQUE_ID_HPP + +#include "iceoryx_hoofs/cxx/newtype.hpp" + +#include + +namespace iox +{ +namespace cxx +{ +/// @brief Unique IDs within a process starting with 1. Monotonic increasing IDs are +/// created with each call to the constructor. The IDs are copy/move constructible/assignable, +/// comparable, sortable and convertable to the underlying value type. +class UniqueId : public cxx::NewType +{ + public: + using ThisType::ThisType; + + /// @brief the constructor creates an ID which is greater than the previous created ID + UniqueId() noexcept; + + private: + static std::atomic g_IdCounter; // initialized in corresponding cpp file +}; + +} // namespace cxx +} // namespace iox + +#endif // IOX_HOOFS_CXX_UNIQUE_ID_HPP diff --git a/iceoryx_hoofs/source/cxx/unique_id.cpp b/iceoryx_hoofs/source/cxx/unique_id.cpp new file mode 100644 index 0000000000..e2be4425c3 --- /dev/null +++ b/iceoryx_hoofs/source/cxx/unique_id.cpp @@ -0,0 +1,31 @@ +// Copyright (c) 2022 by Apex.AI Inc. 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. +// +// SPDX-License-Identifier: Apache-2.0 + +#include "iceoryx_hoofs/internal/cxx/unique_id.hpp" + +namespace iox +{ +namespace cxx +{ +// start with 1, just in case we want to use 0 for a special purpose later on +std::atomic UniqueId::g_IdCounter{1U}; + +UniqueId::UniqueId() noexcept + : ThisType(newtype::internal::ProtectedConstructor, g_IdCounter.fetch_add(1U, std::memory_order_relaxed)) +{ +} +} // namespace cxx +} // namespace iox diff --git a/iceoryx_hoofs/test/moduletests/test_cxx_unique_id.cpp b/iceoryx_hoofs/test/moduletests/test_cxx_unique_id.cpp new file mode 100644 index 0000000000..dae12a01db --- /dev/null +++ b/iceoryx_hoofs/test/moduletests/test_cxx_unique_id.cpp @@ -0,0 +1,141 @@ +// Copyright (c) 2022 by Apex.AI Inc. 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. +// +// SPDX-License-Identifier: Apache-2.0 + +#include "iceoryx_hoofs/internal/cxx/unique_id.hpp" + +#include "iceoryx_hoofs/cxx/attributes.hpp" + +#include "test.hpp" + +#include +#include + +namespace +{ +using namespace ::testing; +using namespace iox::cxx; + +TEST(UniqueId_test, ConstructingUniqueIdWorks) +{ + auto sut IOX_MAYBE_UNUSED = UniqueId(); +} + +TEST(UniqueId_test, ConversionToValueTypeWorks) +{ + auto sut = UniqueId(); + auto value IOX_MAYBE_UNUSED = static_cast(sut); +} + +TEST(UniqueId_test, TwoConsecutiveCreatedUniqueIdsDifferByOne) +{ + auto sut1 = UniqueId(); + auto sut2 = UniqueId(); + auto value1 = static_cast(sut1); + auto value2 = static_cast(sut2); + + EXPECT_THAT(value2 - value1, Eq(1U)); +} + +TEST(UniqueId_test, ComparingTwoUniqueIdsWorks) +{ + auto sut1 = UniqueId(); + auto sut2 = UniqueId(); + + EXPECT_TRUE(sut1 < sut2); + EXPECT_TRUE(sut1 <= sut2); + EXPECT_TRUE(sut1 != sut2); + EXPECT_TRUE(sut2 > sut1); + EXPECT_TRUE(sut2 >= sut1); + EXPECT_FALSE(sut1 == sut2); +} + +TEST(UniqueId_test, CopyConstructingUniqueIdsWorks) +{ + auto id = UniqueId(); + auto idValue = static_cast(id); + auto sut{id}; + auto sutValue = static_cast(sut); + + EXPECT_THAT(sut, Eq(id)); + EXPECT_THAT(sutValue, Eq(idValue)); +} + +TEST(UniqueId_test, CopyAssigningUniqueIdsWorks) +{ + auto id = UniqueId(); + auto idValue = static_cast(id); + auto sut = UniqueId(); + sut = id; + auto sutValue = static_cast(sut); + + EXPECT_THAT(sut, Eq(id)); + EXPECT_THAT(sutValue, Eq(idValue)); +} + +TEST(UniqueId_test, MoveConstructingUniqueIdsWorks) +{ + auto id = UniqueId(); + auto idValue = static_cast(id); + auto sut{std::move(id)}; + auto sutValue = static_cast(sut); + + EXPECT_THAT(sutValue, Eq(idValue)); +} + +TEST(UniqueId_test, MoveAssigningUniqueIdsWorks) +{ + auto id = UniqueId(); + auto idValue = static_cast(id); + auto sut = UniqueId(); + sut = std::move(id); + auto sutValue = static_cast(sut); + + EXPECT_THAT(sutValue, Eq(idValue)); +} + +TEST(UniqueId_test, UniqueIdsAreMonotonicallyIncreasing) +{ + auto id1 = UniqueId(); + auto idValue1 = static_cast(id1); + + auto idValue2 = [] { return static_cast(UniqueId()); }(); + + auto id3 = UniqueId(); + auto idValue3 = static_cast(id3); + + EXPECT_THAT(idValue2 - idValue1, Eq(1U)); + EXPECT_THAT(idValue3 - idValue2, Eq(1U)); +} + +TEST(UniqueId_test, SortingUniqueIdsWorks) +{ + auto id1 = UniqueId(); + auto id2 = UniqueId(); + auto id3 = UniqueId(); + + std::vector sut; + sut.push_back(id2); + sut.push_back(id3); + sut.push_back(id1); + + sort(sut.begin(), sut.end()); + + ASSERT_THAT(sut.size(), Eq(3U)); + EXPECT_THAT(sut[0], Eq(id1)); + EXPECT_THAT(sut[1], Eq(id2)); + EXPECT_THAT(sut[2], Eq(id3)); +} +} // namespace