Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iox-#1036 Builder pattern for message queue #2014

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 18 additions & 17 deletions doc/website/release-notes/iceoryx-unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
- Extend `concatenate`, `operator+`, `unsafe_append` and `append` of `iox::string` for chars [\#208](https://github.com/eclipse-iceoryx/iceoryx/issues/208)
- Extend `unsafe_append` and `append` methods of `iox::string` for `std::string` [\#208](https://github.com/eclipse-iceoryx/iceoryx/issues/208)
- The iceoryx development environment supports multiple running docker containers [\#1410](https://github.com/eclipse-iceoryx/iceoryx/issues/1410)
- Use builder pattern in FileLock [\#1036](https://github.com/eclipse-iceoryx/iceoryx/issues/1036)
- Add the ability to adjust path and file permissions of the file lock
- Create convenience macro for `NewType` [\#1425](https://github.com/eclipse-iceoryx/iceoryx/issues/1425)
- Add posix thread wrapper [\#1365](https://github.com/eclipse-iceoryx/iceoryx/issues/1365)
- Apps send only the heartbeat when monitoring is enabled in roudi [\#1436](https://github.com/eclipse-iceoryx/iceoryx/issues/1436)
Expand Down Expand Up @@ -99,8 +97,17 @@
- Use `GTEST_FAIL` and `GTEST_SUCCEED` instead of `FAIL` and `SUCCEED` [\#1072](https://github.com/eclipse-iceoryx/iceoryx/issues/1072)
- posix wrapper `SharedMemoryObject` is silent on success [\#971](https://github.com/eclipse-iceoryx/iceoryx/issues/971)
- Remove creation design pattern class with in place implementation [\#1036](https://github.com/eclipse-iceoryx/iceoryx/issues/1036)
- posix wrapper `SharedMemoryObject` uses builder pattern instead of creation
- Builder pattern extracted from `helplets.hpp` into `iox/builder.hpp`
- the following classes use the builder pattern instead of creation
- `SharedMemoryObject`
- `MemoryMap`
- `SharedMemory`
- `MessageQueue`
- `FileLock`
- Add the ability to adjust path and file permissions of the file lock
- `Mutex`
- `NamedSemaphore`
- `UnnamedSemaphore`
- Builder pattern extracted from `helplets.hpp` into `iox/builder.hpp`
- Uninteresting mock function calls in tests [\#1341](https://github.com/eclipse-iceoryx/iceoryx/issues/1341)
- `cxx::unique_ptr` owns deleter, remove all deleter classes [\#1143](https://github.com/eclipse-iceoryx/iceoryx/issues/1143)
- Remove `iox::posix::Timer` [\#337](https://github.com/eclipse-iceoryx/iceoryx/issues/337)
Expand All @@ -125,7 +132,6 @@
- Rename `algorithm::max` and `algorithm::min` to `algorithm::maxVal` and `algorithm::minVal` [\#1394](https://github.com/eclipse-iceoryx/iceoryx/issues/1394)
- Extract `iceoryx_hoofs/platform` into separate package `iceoryx_platform` [\#1615](https://github.com/eclipse-iceoryx/iceoryx/issues/1615)
- `cxx::unique_ptr` is no longer nullable [\#1104](https://github.com/eclipse-iceoryx/iceoryx/issues/1104)
- Use builder pattern in mutex [\#1036](https://github.com/eclipse-iceoryx/iceoryx/issues/1036)
- Change return type of `vector::erase` to bool [\#1662](https://github.com/eclipse-iceoryx/iceoryx/issues/1662)
- `ReleativePointer::registerPtr` returns `iox::optional` [\#605](https://github.com/eclipse-iceoryx/iceoryx/issues/605)
- `iox::function` is no longer nullable [\#1104](https://github.com/eclipse-iceoryx/iceoryx/issues/1104)
Expand Down Expand Up @@ -155,26 +161,21 @@

**API Breaking Changes:**

1. Builder pattern in `SharedMemoryObject` instead of creation pattern
1. Builder pattern instead of creation pattern

```cpp
// before
auto sharedMemory = iox::posix::SharedMemoryObject::create("shmAllocate",
16,
iox::posix::AccessMode::READ_WRITE,
iox::posix::OpenMode::PURGE_AND_CREATE,
iox::posix::SharedMemoryObject::NO_ADDRESS_HINT);
auto fooObject = iox::Foo::create("Bar", 42);

// after
auto sharedMemory = iox::posix::SharedMemoryObjectBuilder()
.name("shmAllocate")
.memorySizeInBytes(16)
.accessMode(iox::posix::AccessMode::READ_WRITE)
.openMode(iox::posix::OpenMode::PURGE_AND_CREATE)
.permissions(iox::perms::owner_all)
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.

2. Builder pattern extracted from `helplets.hpp` into `iox/builder.hpp`

```cpp
Expand Down
71 changes: 52 additions & 19 deletions iceoryx_dust/include/iceoryx_dust/posix_wrapper/message_queue.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) 2019 - 2020 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2020 - 2021 by Apex.AI Inc. All rights reserved.
// Copyright (c) 2023 by Mathias Kraus <[email protected]>. 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.
Expand All @@ -17,12 +18,13 @@
#ifndef IOX_DUST_POSIX_WRAPPER_MESSAGE_QUEUE_HPP
#define IOX_DUST_POSIX_WRAPPER_MESSAGE_QUEUE_HPP

#include "iceoryx_dust/design/creation.hpp"
#include "iceoryx_hoofs/internal/posix_wrapper/ipc_channel.hpp"
#include "iceoryx_platform/fcntl.hpp"
#include "iceoryx_platform/mqueue.hpp"
#include "iceoryx_platform/stat.hpp"
#include "iox/builder.hpp"
#include "iox/duration.hpp"
#include "iox/expected.hpp"
#include "iox/optional.hpp"

namespace iox
Expand All @@ -31,11 +33,11 @@ namespace posix
{
/// @brief Wrapper class for posix message queue
///
/// @tparam NON_BLOCKING specifies the type of message queue. A non-blocking message queue will immediately return from
/// a send/receive call if the queue is full/empty. A blocking message has member functions timedSend and timedReceive
/// which allow to specify a maximum timeout duration.
/// @code
/// auto mq = posix::MessageQueue<true>::CreateMessageQueue("/MqName123");
/// auto mq = iox::posix::MessageQueueBuilder()
/// .name("/MqName123")
/// .channelSide(iox::posix::IpcChannelSide::CLIENT)
/// .create();
/// if (mq.has_value())
/// {
/// mq->send("important message, bla.");
Expand All @@ -44,29 +46,36 @@ namespace posix
/// mq->receive(str);
/// }
/// @endcode
class MessageQueue : public DesignPattern::Creation<MessageQueue, IpcChannelError>
class MessageQueue
{
public:
static constexpr mqd_t INVALID_DESCRIPTOR = std::numeric_limits<mqd_t>::max();
static constexpr int32_t ERROR_CODE = -1;
static constexpr uint64_t SHORTEST_VALID_QUEUE_NAME = 2;
static constexpr uint64_t NULL_TERMINATOR_SIZE = 1;
static constexpr uint64_t MAX_MESSAGE_SIZE = 4096;
static constexpr uint64_t MAX_MESSAGE_NUMBER = 10;

/// for calling private constructor in create method
friend class DesignPattern::Creation<MessageQueue, IpcChannelError>;

/// default constructor. The result is an invalid MessageQueue object which can be reassigned later by using the
/// move constructor.
MessageQueue() noexcept;

MessageQueue() noexcept = delete;
MessageQueue(const MessageQueue& other) = delete;
MessageQueue(MessageQueue&& other) noexcept;
MessageQueue& operator=(const MessageQueue& other) = delete;
MessageQueue& operator=(MessageQueue&& other) noexcept;

~MessageQueue() noexcept;

/// @todo iox-#1036 Remove when all channels are ported to the builder pattern
static expected<MessageQueue, IpcChannelError> create(const IpcChannelName_t& name,
const IpcChannelSide channelSide,
const uint64_t maxMsgSize = MAX_MESSAGE_SIZE,
const uint64_t maxMsgNumber = MAX_MESSAGE_NUMBER) noexcept;

/// @todo iox-#1036 Remove when all channels are ported to the builder pattern
bool isInitialized() const noexcept
{
return m_mqDescriptor != INVALID_DESCRIPTOR;
}

static expected<bool, IpcChannelError> unlinkIfExists(const IpcChannelName_t& name) noexcept;

/// @brief send a message to queue using std::string.
Expand All @@ -90,12 +99,15 @@ class MessageQueue : public DesignPattern::Creation<MessageQueue, IpcChannelErro
static expected<bool, IpcChannelError> isOutdated() noexcept;

private:
MessageQueue(const IpcChannelName_t& name,
const IpcChannelSide channelSide,
const size_t maxMsgSize = MAX_MESSAGE_SIZE,
const uint64_t maxMsgNumber = 10U) noexcept;
friend class MessageQueueBuilder;

expected<mqd_t, IpcChannelError> open(const IpcChannelName_t& name, const IpcChannelSide channelSide) noexcept;
MessageQueue(const IpcChannelName_t&& name,
const mq_attr attributes,
mqd_t mqDescriptor,
const IpcChannelSide channelSide) noexcept;

static expected<mqd_t, IpcChannelError>
open(const IpcChannelName_t& name, mq_attr& attributes, const IpcChannelSide channelSide) noexcept;

expected<void, IpcChannelError> close() noexcept;
expected<void, IpcChannelError> unlink() noexcept;
Expand All @@ -119,8 +131,29 @@ class MessageQueue : public DesignPattern::Creation<MessageQueue, IpcChannelErro
/// NOLINTJUSTIFICATION used inside the wrapper so that the user does not have to use this
/// construct from outside
/// NOLINTNEXTLINE(hicpp-signed-bitwise)
static constexpr mode_t m_filemode{S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH};
static constexpr mode_t FILE_MODE{S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH};
};

class MessageQueueBuilder
{
/// @brief Defines the message queue name
IOX_BUILDER_PARAMETER(IpcChannelName_t, name, "")

/// @brief Defines how the message queue is opened, i.e. as client or server
IOX_BUILDER_PARAMETER(IpcChannelSide, channelSide, IpcChannelSide::CLIENT)

/// @brief Defines the max message size of the message queue
IOX_BUILDER_PARAMETER(uint64_t, maxMsgSize, MessageQueue::MAX_MESSAGE_SIZE)

/// @brief Defines the max number of messages for the message queue.
IOX_BUILDER_PARAMETER(uint64_t, maxMsgNumber, MessageQueue::MAX_MESSAGE_NUMBER)

public:
/// @brief create a message queue
/// @return On success a 'MessageQueue' is returned and on failure an 'IpcChannelError'.
expected<MessageQueue, IpcChannelError> create() const noexcept;
};

} // namespace posix
} // namespace iox

Expand Down
Loading
Loading