vx.x.x (xxxx-xx-xx)
Notes
- The minimal supported GCC compiler is now 8.3
- The required C++ standard is now C++17
Features:
- Add bazel asan, usan, tsan build config #1547
- Add bazel clang build config #1998
- Add
command_line.hpp
which contains a macro builder to parse command line arguments quickly and safely #1067 - optional inherits from FunctionalInterface, adds .expect() method #996
- Add clear method for
iox::string
#208 - Add at method and operator[] for
iox::string
#208 - expected inherits from FunctionalInterface, adds .expect() method #996
- Add CI check of used headers against a list #1252
- Add insert method for
iox::string
#208 - Extend compare method of
iox::string
to compare additionally with std::string and char array #208 - Add compare method for
iox::string
and chars #208 - Refactor semaphore #751
- Introduce
UnnamedSemaphore
- Introduce
NamedSemaphore
- Remove old
Semaphore
- Introduce
- Extend
concatenate
,operator+
,unsafe_append
andappend
ofiox::string
for chars #208 - Extend
unsafe_append
andappend
methods ofiox::string
forstd::string
#208 - The iceoryx development environment supports multiple running docker containers #1410
- Create convenience macro for
NewType
#1425 - Add posix thread wrapper #1365
- Apps send only the heartbeat when monitoring is enabled in roudi #1436
- Support Bazel as optional build system #1542
- Exchangable and customizable iceoryx platform #1432
- Support user defined platforms with cmake switch
-DIOX_PLATFORM_PATH
#1619 - See also
website/advanced/custom-iceoryx-platform.md
- Support user defined platforms with cmake switch
- Add equality and inequality operators for
iox::variant
andiox::expected
#1751 - Implement UninitializedArray #1614
- Implement BumpAllocator #1732
- Expand cmake configuration options to enable reducing shared memory consumption. #1803
- Implement PolymorphicHandler #1640
- Implement SemanticString as base class for strong string types. #1942
- Implement UserName as strong string type to represent posix user names. #1942
- Implement FileName, GroupName, Path, FilePath as strong string types. #1942
- Add string::unchecked_at to access character without bound checks. #1942
- Add posix::FileManagementInterface to offer common operations like ownership/permission handling to all file descriptor based constructs. #1952
- Implement dereference operator for smart_lock::Proxy #1966
NewType
supports arithmetic operations and loops #1554- Add
iox::span
#180 - Implement custom error reporting API #1032
- Implement iceoryx platform for FreeRTOS #1982
- Extend 'iceperf' with 'WaitSet' #2003
- Create iceoryx version header for the C-binding #1014
- Create macros to deprecate header and code constructs #2057
- Switch to C++17 on all platforms #2066
- Implement
unsafe_raw_access
iniox::string
and addBufferInfo
struct #1431 - Add the introspection to the ROS release #2099
- Fast POD data in
iox::vector
#2082 - MinGW support for Windows #2150
- Add support for
iox::string
inUnixDomainSocket
and createdunix_domain_socket.inl
#2040 - Add support for
iox::string
inMessageQueue
and createdmessage_queue.inl
#1963 - Add support for
iox::string
inNamedPipe
and creatednamed_pipe.inl
#1693 - Add an
iox1
prefix to all resources created byiceoryx_posh
andRouDi
#2185 - Make iceoryx resource prefix a compile time option #2272
Bugfixes:
- FreeBSD CI build is broken #1338
- High CPU load in blocked publisher is reduced by introducing smart busy loop waiting (adaptive_wait) #1347
- Compile Error : iceoryx_dds/Mempool.hpp: No such file or directory #1364
- RPATH is correctly set up for all libraries and binaries. #1287
- Wrong memory order in concurrent::FIFO #1396
- Iceoryx libraries weren't compiled with
-fPIC
as position independent code #\879 - Restrict runtime (application) names to valid file names to solve failures in the underlying posix constructs #\1419
- CMake config assumes relative
CMAKE_INSTALL_LIBDIR
#1393 - Build error on certain versions of Windows/Visual Studio #1476
- Fix INTERFACE_INCLUDE_DIRECTORIES in CMake #1481
- The testing libs are broken for in source tree usage #1528
- This bug was not part of a release but introduce during the v3 development
- Add "inline" keyword to smart_lock method implementation #1551
- Fix RouDi crash due to uninitialized
ServiceRegistry
chunk #1575 - Add check in
cxx::unique_ptr::get
to avoidnullptr
dereferencing #1571 - Pass
CleanupCapacity
to underlyingiox::function
inScopeGuard
(formerly known ascxx::GenericRAII
) #1594 - Add check in
RelativePointer::get
to avoidnullptr
dereferencing #1596 - iceoryx_posh_testing cannot find iceoryx_hoofs_testing in CMake #1602
- locking_policy.cpp calls error handler without log message #1609
- Implement destructor, copy and move operations in
iox::stack
#1469 gw::GatewayGeneric
sometimes terminates discovery and forward threads immediately #1666m_originId
inmepoo::ChunkHeader
sometimes not set #1668- Remove
cxx::unique_ptr::reset
#1655 - CI uses outdated clang-format #1736
- Avoid UB when accessing
iox::expected
#1750 - Fix double move in
vector::emplace
#1823 - Default roudi_config.toml path is not used #1826
WaitSet::wait
returns if data was send beforeWaitSet::attachState(.., State::HAS_{DATA, REQUEST, RESPONSE})
#1855- Provide a better error message when attempting to create a shared memory in read-only mode #1821
- Can not build iceoryx with gcc 9.4 #1871
- Update iceoryx_integrationtest package to use ROS2 Humble #1906
- Fix potential memory leak in
iox::stack
#1893 - Make
MAX_USER_NAME_LENGTH
andMAX_GROUP_NAME_LENGTH
platform-dependent #1919 - Fix milliseconds in log timestamps #1932
- Alias
invoke_result
to correct implementation based on C++ version #1934 - Fix undefined behaviour in
publishCopyOf
andpublishResultOf
#1963 - ServiceDescription
Interfaces
andINTERFACE_NAMES
do not match #1977 - Implement and test nullptr check in c binding #1106
- Fix
expected<void, Error>
is unusable due tofinal
#1976 - MacOS tests that use
EXPECT_DEATH
stuck #898 - Remove
EXPECT_DEATH
#1613 - ServiceDiscovery uses instrospection MemPools #1359
- LockFreeQueue fails to support move-only types #2067
- Fix musl libc compile (missing sys/stat.h include in mqueue.h for mode_t definition) #2072
- cxx::Expects macro conflicts with Microsoft GSL Expects macro #2080
- Implement move/copy constructor and assignment for
FixedPositionContainer
#2052 - FixedPositionContainer fails to compile on QNX QCC #2084
- Chunk fails to be released when more than 4 GiB of chunks have been allocated #2087
- Fix clang-tidy errors from full-scan nightly build #2060
- Add public functions to create an 'access_rights' object from integer values #2108
- Fix
historyRequest
may be larger thanqueueCapacity
during creating a subscriber #2121 - Unable to acquire file status due to an unknown failure #2023
- Bug in
ListenerImpl
#2137 - Wrong memory order in
MpmcLoFFLi
fence synchronization #2196 - Race condition in
PoshRuntime
during shutdown #2192 - Fix wrong memory orders in SpscFiFo #2167
- Implement missing copy assignment for expected #2216
- Add missing type aliases that conform with STL container types #2220
- Fix
const
value assignment iniox::optional
#2224 - Generated files cause recompilation even without any changes #2210
- Fix span_iterator constructor to prevent assertion when iterating over spans #2216
- Fix span span constructor assert when using begin/end constructor #2253
- Listener examples need to take all samples in the callback #2251
- 'iox::string' tests can exceed the translation unit compilation timeout #2278
Refactoring:
- Separate module specific errors from
iceoryx_hoofs
#1099- Move test specific code to
ErrorHandlerMock
and templatizesetTemporaryErrorHandler()
- Create separate error enum for each module
- Move test specific code to
- Use
GTEST_FAIL
andGTEST_SUCCEED
instead ofFAIL
andSUCCEED
#1072 - posix wrapper
SharedMemoryObject
is silent on success #971 - Remove creation design pattern class with in place implementation #1036
- the following classes use the builder pattern instead of creation
SharedMemoryObject
MemoryMap
SharedMemory
MessageQueue
NamedPipe
UnixDomainSocket
FileLock
- Add the ability to adjust path and file permissions of the file lock
Mutex
NamedSemaphore
UnnamedSemaphore
- Builder pattern extracted from
helplets.hpp
intoiox/builder.hpp
- the following classes use the builder pattern instead of creation
- Uninteresting mock function calls in tests #1341
cxx::unique_ptr
owns deleter, remove all deleter classes #1143- Remove
iox::posix::Timer
#337 - Refactor service discovery tests /#1065 to increase comprehension and cover more test cases
- Remove usage of
std::function
#831 - Replace
MethodCallback
withiox::function
#831 - Remove null-ability
iox::function_ref
#1104 - Remove implicit conversion from
iox::expected
toiox::optional
#1196 - Remove AtomicRelocatablePointer #1512
SignalHandler
returns aniox::expected
inregisterSignalHandler
#1196- Remove the unused
PosixRights
struct #1556 - Move quality level 2 classes to new package
iceoryx_dust
#590- moved back to
hoofs
- moved back to
- Remove unused classes from
iceoryx_hoofs
#590cxx::PoorMansHeap
- Other
internal
classes
- Cleanup helplets #1560
- Move package
iceoryx_dds
to separate repository #1564 - Set
SOVERSION
with project major version for shared libraries in CMake #1308 - Monitoring feature of RouDi is now disabled by default #1580
- Rename
cxx::GenericRAII
toiox::ScopeGuard
#1450 - Rename
algorithm::max
andalgorithm::min
toalgorithm::maxVal
andalgorithm::minVal
#1394 - Extract
iceoryx_hoofs/platform
into separate packageiceoryx_platform
#1615 cxx::unique_ptr
is no longer nullable #1104- Change return type of
vector::erase
to bool #1662 ReleativePointer::registerPtr
returnsiox::optional
#605iox::function
is no longer nullable #1104- Rename
BaseRelativePointer
toUntypedRelativePointer
#605 - Prevent building GoogleTest when
GTest_DIR
is defined #1758 - Refactor
iceoryx_posh_testing
library into own CMakeLists.txt #1516 - Change return type of
cxx::variant::emplace_at_index
andemplace
to void #1394 - Replace uses of
std::cout
,std::cerr
with the iceoryx logger #1756 - Move
IOX_NO_DISCARD
,IOX_FALLTHROUGH
andIOX_MAYBE_UNUSED
toiceoryx_platform
#1726 - Move
cxx::static_storage
fromiceoryx_hoofs
toiceoryx_dust
#1732- moved back to
hoofs
- moved back to
- Remove
algorithm::uniqueMergeSortedContainers
fromalgorithm.hpp
- Move
std::string
conversion function toiceoryx_dust
#1612- moved back to
hoofs
- moved back to
- The posix call
unlink
is directly used inUnixDomainSocket
#1622 - Wrap all C calls in posixCall in IntrospectionApp #1692
- Move
std::chrono
dependency toiceoryx_dust
#536- moved back to
hoofs
- moved back to
- Move
std::string
dependency fromiox::string
tostd_string_support.hpp
iniceoryx_dust
#1612- moved back to
hoofs
- moved back to
- Better align
iox::expected
withstd::expected
#1969 - Use logger for "RouDi is ready for clients" message #1994
- Speed up posh tests #1030
- Roudi Environment independent from Googletest #1533
- Move test class for ctor and assignment operators to hoofs testing #2041
- Refactor
FixedPositionContainer
and move todust
#2044- final location is
hoofs
- final location is
- Cleanup or Remove ObjectPool #66
- Improve process is alive detection #1361
- only partially
- IPC call is replaced with heartbeat via shared memory
- Removed IOX_INTERNAL_MAX_NUMBER_OF_NOTIFIERS and made IOX_MAX_NUMBER_OF_NOTIFIERS configurable again #2083
- Setting IOX_NO_DISCARD in QNX #638
- Replace
iox::byte_t
with std::byte #1900 - Merge
iceoryx_dust
back toiceoryx_hoofs
#2130 - Activate clang-tidy for all the code in iceoryx_hoofs #2184
- Split
iceoryx_hoofs
into logical modules #1391 - Create a flat include structure for
iceoryx_hoofs
#1593 - Handle 'strerror_r' idiosyncrasies in the platform layer #1616
- Fix new clang-tidy-18 warnings #2274
Workflow:
- Remove hash from the branch names #1530
- Automate check for test cases to have UUIDs #1540
- Add Thread Sanitizer to build and test workflow #692
- Document workaround for documentation in internal headers #1293
- The default branch is now
main
#2270
New API features:
API Breaking Changes:
-
Builder pattern instead of creation pattern
// before auto fooObject = iox::Foo::create("Bar", 42); // after auto fooObject = iox::FooBuilder() .name("Bar") .memorySizeInBytes(42) .create();
The refactoring section has a list with all the affected classes. Have a look at the documentation of these classes for more details.
-
Builder pattern extracted from
helplets.hpp
intoiox/builder.hpp
// before #include "iceoryx_hoofs/cxx/helplets.hpp" // after #include "iox/builder.hpp"
-
UnnamedSemaphore
replacesSemaphore
withCreateUnnamed*
option// before #include "iceoryx_hoofs/posix_wrapper/semaphore.hpp" auto semaphore = iox::posix::Semaphore::create(iox::posix::CreateUnnamedSingleProcessSemaphore, 0); // after #include "iox/unnamed_semaphore.hpp" iox::optional<iox::UnnamedSemaphore> semaphore; auto result = iox::UnnamedSemaphoreBuilder() .initialValue(0U) .isInterProcessCapable(true) .create(semaphore);
-
NamedSemaphore
replacesSemaphore
withCreateNamedSemaphore
option// before #include "iceoryx_hoofs/posix_wrapper/semaphore.hpp" auto semaphore = iox::posix::Semaphore::create(iox::posix::CreateNamedSemaphore, "mySemaphoreName", S_IRUSR | S_IWUSR, 0); // after #include "iox/named_semaphore.hpp" iox::optional<iox::NamedSemaphore> semaphore; auto result = iox::NamedSemaphoreBuilder() .name("mySemaphoreName") .openMode(iox::OpenMode::OPEN_OR_CREATE) .permissions(iox::perms::owner_all) .initialValue(0U) .create(semaphore);
-
RoudiApp::waitForSignal
is deprecated// before //// in my custom roudi app implementation uint8_t MyCustomRoudiApp::run() noexcept { // ... waitForSignal(); } // after //// in my custom roudi app implementation uint8_t MyCustomRoudiApp::run() noexcept { // ... iox::waitForTerminationRequest(); }
-
It is not possible to delete a class which is derived from
FunctionalInterface
via a pointer toFunctionalInterface
iox::FunctionalInterface<iox::optional<MyClass>, MyClass, void>* soSmart = new iox::optional<MyClass>{}; delete soSmart; // <- not possible anymore
-
It is not possible to delete a class which is derived from
NewType
via a pointer toNewType
struct Foo : public iox::NewType<uint64_t, iox::newtype::ConstructByValueCopy> { using ThisType::ThisType; }; iox::NewType<uint64_t, iox::newtype::ConstructByValueCopy>* soSmart = new Foo{42}; delete soSmart; // <- not possible anymore
-
It is not possible to use the
NewType
to create type aliases. This was not recommended and is now enforced// before // for the compiler Foo and Bar are the same type using Foo = iox::NewType<uint64_t, iox::newtype::ConstructByValueCopy>; using Bar = iox::NewType<uint64_t, iox::newtype::ConstructByValueCopy>; // after // compile time error when Foo and Bar are mixed up struct Foo : public iox::NewType<uint64_t, iox::newtype::ConstructByValueCopy> { using ThisType::ThisType; }; // or with the IOX_NEW_TYPE macro IOX_NEW_TYPE(Bar, uint64_t, iox::newtype::ConstructByValueCopy);
-
FileLock
uses the builder pattern. Path and permissions can now be set.// before auto fileLock = iox::posix::FileLock::create("lockFileName") .expect("Oh no I couldn't create the lock file"); // after auto fileLock = iox::FileLockBuilder().name("lockFileName") .path("/Now/I/Can/Add/A/Path") .permission(iox::perms::owner_all) .create() .expect("Oh no I couldn't create the lock file");
-
isValidFilePath
is removed useisValidPathToFile
instead.// before bool isCorrect = isValidFilePath("/path/to/file"); // after bool isCorrect = isValidPathToFile("/path/to/file");
-
Remove implicit conversion from
iox::expected
toiox::optional
// before iox::optional<int> myLama = someExpected; // after iox::optional<int> myLama = someExpected.to_optional();
-
Replace implicit conversion of
units::Duration
totimeval
by a conversion method// before units::Duration duration = 42_ms; timeval tv1 = duration; // after units::Duration duration = 42_ms; timveal tv = duration.timeval();
-
registerSignalHandler
returns guard packed inside expected// before //// unable to determine if an error occurred in the underlying posix calls auto signalGuard = iox::posix::registerSignalHandler(iox::posix::Signal::INT, sigHandler); // after auto signalGuard = iox::registerSignalHandler(iox::PosixSignal::INT, sigHandler); if (signalGuard.has_error()) { // perform error handling }
-
Moved or removed various functions from helplets
// before #include "iceoryx_hoofs/cxx/helplets.hpp" iox::cxx::forEach(container, [&] (element) { /* do stuff with element */ }); // after for (const auto& element: container) { /* do stuff with element */ }
// before #include "iceoryx_hoofs/cxx/helplets.hpp" iox::cxx::greater_or_equal(..); iox::cxx::range(..); iox::cxx::BestFittingType(..); iox::cxx::isPowerOfTwo(..); // after #include "iox/algorithm.hpp" iox::greater_or_equal(..); iox::range(..); iox::BestFittingType(..); iox::isPowerOfTwo(..);
// before #include "iceoryx_hoofs/cxx/helplets.hpp" iox::cxx::align(..); iox::cxx::alignedAlloc(..); iox::cxx::alignedFree(..); iox::cxx::maxAlignment(..); iox::cxx::maxSize(..); // after #include "iox/memory.hpp" iox::align(..); iox::alignedAlloc(..); iox::alignedFree(..); iox::maxAlignment(..); iox::maxSize(..);
// before #include "iceoryx_hoofs/cxx/helplets.hpp" iox::cxx::isValidPathEntry(..); iox::cxx::isValidFileName(..); iox::cxx::isValidPathToFile(..); iox::cxx::isValidPathToDirectory(..); iox::cxx::doesEndWithPathSeparator(..); // after #include "iox/filesystem.hpp" iox::isValidPathEntry(..); iox::isValidFileName(..); iox::isValidPathToFile(..); iox::isValidPathToDirectory(..); iox::doesEndWithPathSeparator(..);
// before #include "iceoryx_hoofs/cxx/helplets.hpp" template <> constexpr DestType iox::cxx::from<SourceType, DestType>(const SourceType value); iox::cxx::into(..); // after #include "iox/into.hpp" template <> constexpr DestType iox::from<SourceType, DestType>(const SourceType value); iox::into(..);
-
Remove
enumTypeAsUnderlyingType
constexpr const char* SOME_ENUM_STRINGS[] = {"FOO", "BAR"}; // before std::cout << SOME_ENUM_STRINGS[iox::cxx::enumTypeAsUnderlyingType(someEnum)] << std::endl; // after std::cout << SOME_ENUM_STRINGS[static_cast<uint64_t>(someEnum)] << std::endl;
Note: The recommended enum to string conversion pattern is as following
constexpr const char* asStringLiteral(const SOME_ENUM value) noexcept { switch (value) { case SOME_ENUM::FOO: return "SOME_ENUM::FOO"; case SOME_ENUM::BAR: return "SOME_ENUM::BAR"; } return "SOME_ENUM::UNDEFINED_VALUE"; }
-
Remove
convertEnumToString
constexpr const char* SOME_ENUM_STRINGS[] = {"FOO", "BAR"}; // before std::cout << iox::cxx::convertEnumToString(SOME_ENUM_STRINGS, someEnum] << std::endl; // after std::cout << SOME_ENUM_STRINGS[static_cast<uint64_t>(someEnum)] << std::endl;
Note: The recommended enum to string conversion pattern is as following
constexpr const char* asStringLiteral(const SOME_ENUM value) noexcept { switch (value) { case SOME_ENUM::FOO: return "SOME_ENUM::FOO"; case SOME_ENUM::BAR: return "SOME_ENUM::BAR"; } return "SOME_ENUM::UNDEFINED_VALUE"; }
-
Replace
strlen2
with more genericiox::size
constexpr const char LITERAL1[] {"FOO"}; constexpr const char LITERAL2[20] {"BAR"}; constexpr const uint32_t ARRAY[42] {}; // before std::cout << iox::cxx::strlen2(LITERAL1) << std::endl; // prints 3 std::cout << iox::cxx::strlen2(LITERAL2) << std::endl; // prints 19 // after #include "iox/size.hpp" std::cout << iox::size(LITERAL1) << std::endl; // prints 4 std::cout << iox::size(LITERAL2) << std::endl; // prints 20 std::cout << iox::size(ARRAY) << std::endl; // prints 42
-
Rename
cxx::GenericRAII
toiox::ScopeGuard
// before #include "iceoryx_hoofs/cxx/generic_raii.hpp" iox::cxx::GenericRAII {[]() { // do on creation },[]() { // do on destruction }}; // after #include "iox/scope_guard.hpp" iox::ScopeGuard {[]() { // do on creation },[]() { // do on destruction }};
-
Rename
algorithm::max
andalgorithm::min
toalgorithm::maxVal
andalgorithm::minVal
// before #include "iceoryx_hoofs/cxx/algorithm.hpp" constexpr uint32_t MAX_VAL = algorithm::max(3, 1890, 57); constexpr uint32_t MIN_VAL = algorithm::min(3, 1890, 57); // after #include "iox/algorithm.hpp" constexpr uint32_t MAX_VAL = algorithm::maxVal(3, 1890, 57); constexpr uint32_t MIN_VAL = algorithm::minVal(3, 1890, 57);
-
ReleativePointer::registerPtr
returnsiox::optional
// before uint64_t id = RelativePointer::register(startAddress, numBytes); if(id == INVALID_ID) { // Early exit } // after auto maybeId = RelativePointer::register(startAddress, numBytes); if(!id.has_value()) { // Early exit }
-
Renamed
BaseRelativePointer
toUntypedRelativePointer
and removed it from namespacerp::
// before #include "iceoryx_hoofs/internal/relocatable_pointer/base_relative_pointer.hpp" iox::rp::BaseRelativePointer myUntypedRelativePointer; // after #include "iox/relative_pointer.hpp" iox::UntypedRelativePointer myUntypedRelativePointer;
-
The
CMakeLists.txt
of apps using iceoryx need to addiceoryx_platform
# before cmake_minimum_required(VERSION 3.16) project(example) find_package(iceoryx_posh CONFIG REQUIRED) find_package(iceoryx_hoofs CONFIG REQUIRED) get_target_property(ICEORYX_CXX_STANDARD iceoryx_posh::iceoryx_posh CXX_STANDARD) // obsolete include(IceoryxPackageHelper) include(IceoryxPlatform) # after cmake_minimum_required(VERSION 3.16) project(example) find_package(iceoryx_platform REQUIRED) # new find_package(iceoryx_posh CONFIG REQUIRED) find_package(iceoryx_hoofs CONFIG REQUIRED) include(IceoryxPackageHelper) include(IceoryxPlatform) include(IceoryxPlatformSettings) # new
-
iceoryx_hoofs/platform
was moved into separate packageiceoryx_platform
. All includes must be adjusted.// before #include "iceoryx_hoofs/platform/some_header.hpp" // after #include "iceoryx_platform/some_header.hpp"
-
cxx::unique_ptr
is no longer nullable and does not have areset
method anymore// before cxx::unique_ptr<int> myPtr(ptrToInt, someDeleter); cxx::unique_ptr<int> emptyPtr(nullptr, someDeleter); if (myPtr) { // required since the object could always be null std::cout << *myPtr << std::endl; } myPtr.reset(ptrToOtherInt); myPtr.release(); // after iox::unique_ptr<int> myPtr(ptrToInt, someDeleter); iox::optional<iox::unique_ptr<int>> emptyPtr(nullopt); // if unique_ptr shall be nullable use optional // no more null check required since it is no longer nullable std::cout << *myPtr << std::endl; myPtr = std::move(uniquePtrToAnotherInt); // deleter(myPtr) is called before move iox::unique_ptr<int>::release(std::move(myPtr)); // release consumes myPtr
Compilers like
gcc-12>
andclang>14
as well as static code analysis tools likeclang-tidy
will warn the user with a used after move warning when one accesses a moved object. Accessing a movedunique_ptr
is well defined and behaves like dereferencing anullptr
. -
mutex
must be always stored inside aniox::optional
and must use the builder pattern for construction// before bool isRecursiveMutex = true; mutex myMutex(isRecursiveMutex); myMutex.lock(); // after iox::optional<iox::mutex> myMutex; iox::MutexBuilder() .mutexType(iox::MutexType::RECURSIVE) .create(myMutex); myMutex->lock();
-
Change return type of
vector::erase
from iterator to bool// before auto* iter = myCxxVector.erase(myCxxVector.begin()); // after bool success = myCxxVector.erase(myCxxVector.begin());
-
iox::function
is no longer nullable.// before iox::cxx::function<void()> helloFunc = []{ std::cout << "hello world\n"; }; iox::cxx::function<void()> emptyFunction; if (helloFunc) { // required since the object could always be null helloFunc(); } // after iox::function<void()> helloFunc = []{ std::cout << "hello world\n"; }; iox::optional<iox::function<void()>> emptyPtr(nullopt); // if function shall be nullable use optional // no more null check required since it is no longer nullable helloFunc();
Compilers like
gcc-12>
andclang>14
as well as static code analysis tools likeclang-tidy
will warn the user with a used after move warning when one accesses a moved object. Accessing a movedfunction
is well defined and behaves like dereferencing anullptr
. -
LogLevel
enum tags are renamed to better match the log4j log levelsbefore after kOff
OFF
kFatal
FATAL
kError
ERROR
kWarn
WARN
kInfo
INFO
kDebug
DEBUG
kVerbose
TRACE
In the C binding the
Iceoryx_LogLevel_Verbose
changed toIceoryx_LogLevel_Trace
. -
LogLevel
enum moved fromiceoryx_hoofs/log/logcommon.hpp
toiox/iceoryx_hoofs_types.hpp
-
Using multiple logger instances and logging directly via a logger instance in not supported anymore out of the box
// before #include "iceoryx_hoofs/log/logmanager.hpp" auto& logger = iox::log::createLogger("MyComponent", "MyContext", iox::log::LogLevel::kInfo); logger.LogInfo() << "Hello World " << 42; // after #include "iox/logging.hpp" iox::log::Logger::init(iox::log::LogLevel::INFO); IOX_LOG(INFO, "Hello World " << 42);
-
Setting the default log level changed
// before #include "iceoryx_hoofs/log/logmanager.hpp" iox::log::LogManager::GetLogManager().SetDefaultLogLevel(iox::log::LogLevel::kError); // after #include "iox/logging.hpp" iox::log::Logger::init(iox::log::LogLevel::ERROR);
Please look at the logger design document for more details like setting the log level via environment variables.
-
Changing the log level at runtime changed
// before logger.SetLogLevel(); // directly on the instance // after iox::log::Logger::setLogLevel(iox::log::LogLevel::DEBUG);
-
Using the logger in libraries is massively simplified
// before // ==== file foo_logging.hpp ==== #ifndef FOO_LOGGING_HPP_INCLUDED #define FOO_LOGGING_HPP_INCLUDED #include "iceoryx_hoofs/log/logging_free_function_building_block.hpp" namespace foo { struct LoggingComponent { static constexpr char Ctx[] = "FOO"; static constexpr char Description[] = "Log context of the FOO component!"; }; static constexpr auto LogFatal = iox::log::ffbb::LogFatal<LoggingComponent>; static constexpr auto LogError = iox::log::ffbb::LogError<LoggingComponent>; static constexpr auto LogWarn = iox::log::ffbb::LogWarn<LoggingComponent>; static constexpr auto LogInfo = iox::log::ffbb::LogInfo<LoggingComponent>; static constexpr auto LogDebug = iox::log::ffbb::LogDebug<LoggingComponent>; static constexpr auto LogVerbose = iox::log::ffbb::LogVerbose<LoggingComponent>; } // namespace foo #endif // FOO_LOGGING_HPP_INCLUDED // ==== file foo_logging.cpp ==== #include "foo_logging.hpp" namespace foo { constexpr char ComponentPosh::Ctx[]; constexpr char ComponentPosh::Description[]; } // namespace foo // ==== file bar.cpp ==== #include "foo_logging.hpp" namespace foo { void myFunc() { LogInfo() << "Hello World " << 42; } } // after // ==== file bar.cpp ==== #include "iox/logging.hpp" namespace foo { void myFunc() { IOX_LOG(INFO, "Hello World " << 42); } }
-
Free function logger calls changed
before after LogFatal() << "x" << 42
IOX_LOG(FATAL, "x" << 42)
LogError() << "x" << 42
IOX_LOG(ERROR, "x" << 42)
LogWarn() << "x" << 42
IOX_LOG(WARN, "x" << 42)
LogInfo() << "x" << 42
IOX_LOG(INFO, "x" << 42)
LogDebug() << "x" << 42
IOX_LOG(DEBUG, "x" << 42)
LogVerbose() << "x" << 42
IOX_LOG(TRACE, "x" << 42)
-
Logger formatting changed
// before LogInfo() << iox::log::HexFormat(42); LogInfo() << iox::log::BinFormat(73); LogInfo() << iox::log::RawBuffer(buf); // after IOX_LOG(INFO, iox::log::hex(42)); IOX_LOG(INFO, iox::log::oct(37)); IOX_LOG(INFO, iox::log::bin(73)); IOX_LOG(INFO, iox::log::raw(buf));
-
Creating an instance of
LogStream
does not work anymore// before auto stream = LogInfo(); stream << "fibonacci: " for(auto fib : {1, 1, 2, 3, 5, 8}) { stream << fib << ", "; } stream << "..."; stream.Flush(); // after IOX_LOG(INFO, [] (auto& stream) -> auto& { stream << "fibonacci: " for(auto fib : {1, 1, 2, 3, 5, 8}) { stream << fib << ", "; } stream << "..."; return stream; });
-
Testing of
LogStream::operator<<
overload for custom types changed// before Logger_Mock loggerMock; iox::log::LogStream(loggerMock) << myType; ASSERT_THAT(loggerMock.m_logs.size(), Eq(1U)); EXPECT_THAT(loggerMock.m_logs[0].message, StrEq(EXPECTED_STRING)); // after iox::testing::Logger_Mock loggerMock; IOX_LOGSTREAM_MOCK(loggerMock) << myType; ASSERT_THAT(loggerMock.logs.size(), Eq(1U)); EXPECT_THAT(loggerMock.logs[0].message, StrEq(EXPECTED_STRING));
-
Suppressing the logger output in tests
// before // using gTest ::testing::internal::CaptureStdout() or ::testing::internal::CaptureStderr() // in every test fixture setup method. This also suppresses the output of the sanitizer // and makes debugging of CI failures unnecessary hard. In addition, it might crash the unittest // when `EXPECT_DEATH` is used // after // ==== unittests.cpp ==== #include "iceoryx_hoofs/testing/testing_logger.hpp" #include <gtest/gtest.h> int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); iox::testing::TestingLogger::init(); return RUN_ALL_TESTS(); }
The log messages are cached and printed when a test fails. To print log messages also for passed tests, the
IOX_TESTING_ALLOW_LOG
environment variable can be used, e.g.IOX_TESTING_ALLOW_LOG=ON ./unittests --gtest_filter=MyTest\*
. This might be helpful to debug tests. -
Checking the log message of test objects in unit tests
// before // some wild stuff with std::clog redirecting or ::testing::internal::CaptureStdout() sut.methodCallWithLogOutput(); // some wild stuff getting the output from the redirected clog or ::testing::internal::internal::GetCapturedStdout() // after #include "iceoryx_hoofs/testing/testing_logger.hpp" sut.methodCallWithLogOutput(); if (iox::testing::TestingLogger::doesLoggerSupportLogLevel(iox::log::LogLevel::ERROR)) { auto logMessages = iox::testing::TestingLogger::getLogMessages(); ASSERT_THAT(logMessages.size(), Eq(1U)); EXPECT_THAT(logMessages[0], HasSubstr(expectedOutput)); }
Have a look at the logger design document for more details on how to setup the testing logger.
-
Flat include structure and namespace for
iceoryx_hoofs
There was quite a big refactoring in
iceoryx_hoofs
and the header are now in a flat structure and namespace with some small exceptions like concurrent constructs being in theiox::concurrent
namespace.// before #include "iceoryx_hoofs/cxx/vector.hpp" iox::cxx::vector<bool, 2> b; // after #include "iox/vector.hpp" iox::vector<bool, 2> b;
The same pattern applies to the other header in
icoryx_hoofs
.Some, but not all, header are still available from the legacy path. Those header will generate a deprecation warning and will be removed in a future release.
-
Use proper aligned
iox::UninitializedArray
instead of C-style array// before char myCharArray[Capacity]; using element_t = uint8_t[sizeof(T)]; alignas(T) element_t myAlignedArray[Capacity]; // after #include "iox/uninitialized_array.hpp" iox::UninitializedArray<char, Capacity, iox::ZeroedBuffer> myCharArray; iox::UninitializedArray<T, Capacity> myAlignedArray;
-
Move multiple classes fromThey are still iniceoryx_hoofs
toiceoryx_dust
iceoryx_hoofs
but the include path changed nevertheless// before #include "iceoryx_hoofs/cxx/forward_list.hpp" // after #include "iox/forward_list.hpp"
// before #include "iceoryx_hoofs/design_pattern/creation.hpp" // after // fully removed
// before #include "iceoryx_hoofs/internal/cxx/static_storage.hpp" // after #include "iox/static_storage.hpp"
// before #include "iceoryx_hoofs/internal/file_reader/file_reader.hpp" // after #include "iox/file_reader.hpp"
// before #include "iceoryx_hoofs/internal/objectpool/objectpool.hpp" // after // fully removed
// before #include "iceoryx_hoofs/internal/relocatable_pointer/relocatable_ptr.hpp" // after #include "iox/relocatable_ptr.hpp"
// before #include "iceoryx_hoofs/posix_wrapper/internal/message_queue.hpp" // after #include "iox/message_queue.hpp"
// before #include "iceoryx_hoofs/posix_wrapper/named_pipe.hpp" // after #include "iox/named_pipe.hpp"
// before #include "iceoryx_hoofs/posix_wrapper/signal_watcher.hpp" // after #include "iox/signal_watcher.hpp"
// before #include "iceoryx_hoofs/cxx/serialization.hpp" // after #include "iox/detail/serialization.hpp"
// before #include "iceoryx_hoofs/cxx/convert.hpp" // after #include "iox/detail/convert.hpp"
-
Move the conversions functions forThey are still instd::string
toiceoryx_dust
:iceoryx_hoofs
but the include path changed nevertheless// before std::string myStdString("foo"); // std::string to iox::string iox::string<3> myIoxString(TruncateToCapacity, myStdString); // iox::string to std::string std::string myConvertedIoxString = static_cast<std::string>(myIoxString); // after #include "iox/std_string_support.hpp" std::string myStdString("foo"); // std::string to iox::string with truncation when source string exceeds capacity auto myIoxString = iox::into<iox::lossy<iox::string<3>>>(myStdString); // returns a 'iox::string<3>' // std::string to iox::string with fallible conversion when source string exceeds capacity auto maybeMyIoxString = iox::into<iox::optional<iox::string<3>>>(myStdString); // returns a 'iox::optional<iox::string<3>>' // iox::string to std::string auto myConvertedIoxString = iox::into<std::string>(myIoxString); // returns a 'std::string'
-
In order to use the comparison or
operator<<
operators,insert
,find
,unsafe_append
functions forstd::string
together withiox::string
include the support header:// before std::string myStdString("foo"); iox::string<3> myIoxString("foo"); if(myIoxString == myStdString) { .. } // after #include "iox/std_string_support.hpp" std::string myStdString("foo"); iox::string<3> myIoxString("foo"); if(myIoxString == myStdString) { .. }
-
Move and rename
DeadlineTimer
// before #include "iceoryx_hoofs/cxx/deadline_timer.hpp" iox::cxx::DeadlineTimer myTimer; // after #include "iox/deadline_timer.hpp" iox::deadline_timer myTimer;
-
Changed include path of
iox::units::Duration
// before #include "iceoryx_hoofs/internal/units/duration.hpp" // after #include "iox/duration.hpp"
-
The
perms
enum is replaced by theaccess_rights
class// before iox::perms foo { iox::perms::owner_all | iox::perms::group_read }; // after iox::access_rights foo { iox::perms::owner_all | iox::perms::group_read };
-
Deprecating
byte_t
in favour ofstd::byte
// before iox::byte_t m_size; // after std::byte m_size;
-
Move conversion methods fromThey are still induration.hpp
toiceoryx_dust
iceoryx_hoofs
but the include path changed nevertheless// before std::chrono::milliseconds chronoDuration = 1_ms; iox::units::Duration ioxDuration(chronoDuration); // after #include "iox/std_chrono_support.hpp" std::chrono::milliseconds chronoDuration = 1_ms; iox::units::Duration ioxDuration{into<iox::units::Duration>(chronoDuration)};
-
Replace error only
expected<E>
withvoid
value typeexpected<void, E>
// before iox::expected<MyCustomError> foo(); // after iox::expected<void, MyCustomError> foo();
-
iox::success
andiox::error
are deprecated in favour ofok
anderr
free functions// before return iox::success<void>(); // after return iox::ok(); // before return iox::success<bool>(true); // after return iox::ok(true); // before return iox::error<MyCustomError>(MyCustomError::ERROR_CODE); // after return iox::err(MyCustomError::ERROR_CODE);
-
expected::get_error
is deprecated in favour ofexpected::error
// before auto e = exp.get_error(); // after auto e = exp.error();
-
UnixDomainSocket
,MessageQueue
andNamedPipe
are not default constructible anymore// before iox::posix::UnixDomainSocket socket; // after // option 1 iox::optional<iox::UnixDomainSocket> socket; // option 2 iox::UnixDomainSocket socket { UnixDomainSocketBuilder() .name("foo") .channelSide(iox::PosixIpcChannelSide::CLIENT) .create() .expect("Valid UnixDomainSocket") };
-
iox::roudi::RouDiEnvironment
is moved toiox::roudi_env::RouDiEnv
and in a separate libraryThere is still an alias on the old location with a deprecation warning. The API also changed a bit.
// before #include "iceoryx_posh/testing/roudi_environment/roudi_environment.hpp" iox::roudi::RouDiEnvironment roudiEnv{/*config*/}; // after #include "iceoryx_posh/roudi_env/roudi_environment.hpp" iox::roudi_env::RouDiEnv roudiEnv{/*config*/}; // before roudiEnv.InterOpWait(); // after roudiEnv.triggerDiscoveryLoopAndWaitToFinish(); // before roudiEnv.SetInterOpWaitingTime(/*chrono*/); // after roudiEnv.setDiscoveryLoopWaitToFinishTimeout(/*units::Duration*/);
It is now also possible to directly link to
iceoryx_posh::iceoryx_posh_roudi_env
which has no dependency to gTest. -
Expects
andEnsures
macros are replaced withIOX_ENFORCE
from the new error handling concept// before #include "iceoryx_hoofs/cxx/requires.hpp" iox::cxx::Expects(foo == true); iox::cxx::Ensures(foo == true); // after #include "iox/assertions.hpp" IOX_ENFORCE(foo == true);
-
IOX_MAYBE_UNUSED
,IOX_FALLTHROUGH
andIOX_NO_DISCARD
are deprecatedWith the switch to C++17
[[maybe_unused]]
,[[fallthrough]]
and[[no_discard]]
are available and should be used instead of the macros. -
posixCall
macro is renamed toIOX_POSIX_CALL
// before iox::posix::posixCall(open)("/hypnotoad"); // after IOX_POSIX_CALL(open)("/hypnotoad");
-
iox::posix::getSchedulerPriorityMinimum
andiox::posix::getSchedulerPriorityMaximum
has become internal API -
The concurrent queues have gained a
Spsc
orMpsc
prefix// before #include "iceoryx_hoofs/concurrent/lockfree_queue.hpp" iox::concurrent::LockFreeQueue q; // after #include "iox/mpmc_lockfree_queue.hpp" iox::concurrent::MpmcLockFreeQueue q;
-
Payload Size for Memory Chunks is now
uin64_t
. Hence theChunkHeader
(iceoryx_posh/mepoo/chunk_header.hpp) layout changes andm_chunkHeaderVersion
is getting increased. Moreover many functions' signatures are also affected by this change. -
iox::RouDiConfig_t
is renamed toiox::IceoryxConfig
to prevent confusion withiox::config::RouDiConfig
which is a part ofiox::RouDiConfig_t
// before iox::RouDiConfig_t config; // after iox::IceoryxConfig config;
-
The
iox::roudi::RouDi
class takes aiox::config::RouDiConfig
instead of aiox::roudi::RouDi::RoudiStartupParameters
as ctor argument// before static optional<IceOryxRouDiComponents> m_rouDiComponents; auto componentsScopeGuard = makeScopedStatic(m_rouDiComponents, m_config); static optional<RouDi> roudi; auto roudiScopeGuard = makeScopedStatic(roudi, m_rouDiComponents.value().rouDiMemoryManager, m_rouDiComponents.value().portManager, RouDi::RoudiStartupParameters{m_monitoringMode, true, RouDi::RuntimeMessagesThreadStart::IMMEDIATE, m_compatibilityCheckLevel, m_processKillDelay, m_processTeminationDelay}); // after static optional<IceOryxRouDiComponents> m_rouDiComponents; auto componentsScopeGuard = makeScopedStatic(m_rouDiComponents, m_config); static optional<RouDi> roudi; auto roudiScopeGuard = makeScopedStatic( roudi, m_rouDiComponents.value().rouDiMemoryManager, m_rouDiComponents.value().portManager, m_config);
-
The
iox::config::CmdLineArgs_t
parameter is removed from theiox::roudi::IceoryxRouDiApp
andiox::roudi::RouDiApp
ctorsIn case the config is created via the parsing of the config file, the
parse
function will add the parameter from the cmd line args to the config.// before iox::config::TomlRouDiConfigFileProvider configFileProvider(cmdLineArgs.value()); auto config = configFileProvider.parse(); if (config.has_error()) { // error handling } iox::roudi::IceOryxRouDiApp roudi(cmdLineArgs.value(), config.value()); // after iox::config::TomlRouDiConfigFileProvider configFileProvider(cmdLineArgs.value()); auto config = configFileProvider.parse(); if (config.has_error()) { // error handling } if (!cmdLineArgs.value().run) { return 0; } iox::roudi::IceOryxRouDiApp roudi(config.value());
In case the config is created manually, the cmd line args also need to be copied manually to the config.
// before iox::RouDiConfig_t config = iox::RouDiConfig_t().setDefaults(); iox::roudi::IceOryxRouDiApp roudi(cmdLineArgs.value(), config.value()); // after iox::IceoryxConfig config = iox::IceoryxConfig().setDefaults(); static_cast<iox::config::RouDiConfig>(config) = cmdLineArgs.value().roudiConfig; iox::roudi::IceOryxRouDiApp roudi(config);
-
The
iox::config::CmdLineArgs_t
now contains a singleiox::config::RouDiConfig
instead of multiple distinct fields// before auto logLevel = cmdArgs.logLevel; // after auto logLevel = cmdArgs.roudiConfig.logLevel;
-
The non-functional
iox::popo::Node
was removed -
32-bit support is disabled by default. For development purposes iceoryx can be build with the
-DIOX_IGNORE_32_BIT_CHECK=ON