diff --git a/doc/website/release-notes/iceoryx-unreleased.md b/doc/website/release-notes/iceoryx-unreleased.md index 3963b0ffb8..fbda0a559b 100644 --- a/doc/website/release-notes/iceoryx-unreleased.md +++ b/doc/website/release-notes/iceoryx-unreleased.md @@ -59,6 +59,8 @@ - MinGW support for Windows [#2150](https://github.com/eclipse-iceoryx/iceoryx/issues/2150) - Add support for `iox::string` in `UnixDomainSocket` and created `unix_domain_socket.inl` [#2040](https://github.com/eclipse-iceoryx/iceoryx/issues/2040) - Add support for `iox::string` in `MessageQueue` and created `message_queue.inl` [#1963](https://github.com/eclipse-iceoryx/iceoryx/issues/1963) +- Add support for `iox::string` in `NamedPipe` and created `named_pipe.inl` [#1693](https://github.com/eclipse-iceoryx/iceoryx/issues/1693) + **Bugfixes:** diff --git a/iceoryx_hoofs/posix/ipc/include/iox/detail/named_pipe.inl b/iceoryx_hoofs/posix/ipc/include/iox/detail/named_pipe.inl new file mode 100644 index 0000000000..f52015de23 --- /dev/null +++ b/iceoryx_hoofs/posix/ipc/include/iox/detail/named_pipe.inl @@ -0,0 +1,128 @@ +// Copyright 2024, Eclipse Foundation and the iceoryx contributors. 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_POSIX_IPC_NAMED_PIPE_INL +#define IOX_HOOFS_POSIX_IPC_NAMED_PIPE_INL + +#include "iox/duration.hpp" +#include "iox/into.hpp" +#include "iox/named_pipe.hpp" + +namespace iox +{ +template +expected NamedPipe::trySend(const iox::string& message) const noexcept +{ + static_assert(N <= MAX_MESSAGE_SIZE, "Size exceeds transmission limit!"); + + auto result = m_data->sendSemaphore().tryWait(); + IOX_EXPECTS(!result.has_error()); + + if (*result) + { + IOX_DISCARD_RESULT(m_data->messages.push(message)); + IOX_EXPECTS(!m_data->receiveSemaphore().post().has_error()); + return ok(); + } + return err(PosixIpcChannelError::TIMEOUT); +} + +template +expected NamedPipe::send(const iox::string& message) const noexcept +{ + static_assert(N <= MAX_MESSAGE_SIZE, "Size exceeds transmission limit!"); + + IOX_EXPECTS(!m_data->sendSemaphore().wait().has_error()); + IOX_DISCARD_RESULT(m_data->messages.push(message)); + IOX_EXPECTS(!m_data->receiveSemaphore().post().has_error()); + + return ok(); +} + +template +expected NamedPipe::timedSend(const iox::string& message, + const units::Duration& timeout) const noexcept +{ + static_assert(N <= MAX_MESSAGE_SIZE, "Size exceeds transmission limit!"); + + auto result = m_data->sendSemaphore().timedWait(timeout); + IOX_EXPECTS(!result.has_error()); + + if (*result == SemaphoreWaitState::NO_TIMEOUT) + { + IOX_DISCARD_RESULT(m_data->messages.push(message)); + IOX_EXPECTS(!m_data->receiveSemaphore().post().has_error()); + return ok(); + } + return err(PosixIpcChannelError::TIMEOUT); +} + +template +expected NamedPipe::receive(iox::string& message) const noexcept +{ + IOX_EXPECTS(!m_data->receiveSemaphore().wait().has_error()); + auto msg = m_data->messages.pop(); + if (msg.has_value()) + { + IOX_EXPECTS(!m_data->sendSemaphore().post().has_error()); + message = *msg; + return ok(); + } + return err(PosixIpcChannelError::INTERNAL_LOGIC_ERROR); +} + +template +expected NamedPipe::tryReceive(iox::string& message) const noexcept +{ + auto result = m_data->receiveSemaphore().tryWait(); + IOX_EXPECTS(!result.has_error()); + + if (*result) + { + auto msg = m_data->messages.pop(); + if (msg.has_value()) + { + IOX_EXPECTS(!m_data->sendSemaphore().post().has_error()); + message = *msg; + } + return err(PosixIpcChannelError::INTERNAL_LOGIC_ERROR); + } + + return err(PosixIpcChannelError::TIMEOUT); +} + +template +expected NamedPipe::timedReceive(iox::string& message, + const units::Duration& timeout) const noexcept +{ + auto result = m_data->receiveSemaphore().timedWait(timeout); + IOX_EXPECTS(!result.has_error()); + + if (*result == SemaphoreWaitState::NO_TIMEOUT) + { + auto msg = m_data->messages.pop(); + if (msg.has_value()) + { + IOX_EXPECTS(!m_data->sendSemaphore().post().has_error()); + message = *msg; + return ok(); + } + return err(PosixIpcChannelError::INTERNAL_LOGIC_ERROR); + } + return err(PosixIpcChannelError::TIMEOUT); +} +} // namespace iox + +#endif \ No newline at end of file diff --git a/iceoryx_hoofs/posix/ipc/include/iox/named_pipe.hpp b/iceoryx_hoofs/posix/ipc/include/iox/named_pipe.hpp index b9d7412aff..1cd5e1ade7 100644 --- a/iceoryx_hoofs/posix/ipc/include/iox/named_pipe.hpp +++ b/iceoryx_hoofs/posix/ipc/include/iox/named_pipe.hpp @@ -104,6 +104,55 @@ class NamedPipe /// @return on success a string containing the message, otherwise an error which describes the failure expected timedReceive(const units::Duration& timeout) const noexcept; + /// @brief tries to send a message via the named pipe. if the pipe is full PosixIpcChannelError::TIMEOUT is returned + /// @tparam N capacity of the iox::string + /// @param[in] message the message to send + /// @return on failure an error which describes the failure + template + expected trySend(const iox::string& message) const noexcept; + + /// @brief sends a message via the named pipe. if the pipe is full this call is blocking until the message could be + /// delivered + /// @tparam N capacity of the iox::string, is not allowed to be longer then MAX_MESSAGE_SIZE + /// @param[in] message the message which should be sent + /// @return success when message was sent otherwise an error which describes the failure + template + expected send(const iox::string& message) const noexcept; + + /// @brief sends a message via the named pipe. + /// @tparam N capacity of the iox::string, is not allowed to be longer then MAX_MESSAGE_SIZE + /// @param[in] message the message which should be sent + /// @param[in] timeout the timeout on how long this method should retry to send the message + /// @return success when message was sent otherwise an error which describes the failure + template + expected timedSend(const iox::string& message, + const units::Duration& timeout) const noexcept; + + /// @brief tries to receive a message via the named pipe. if the pipe is empty PosixIpcChannelError::TIMEOUT is + /// returned + /// @tparam N capacity of the iox::string + /// @param[in] message the message to receive + /// @return on success a string containing the message, otherwise an error which describes the failure + template + expected tryReceive(iox::string& message) const noexcept; + + /// @brief receives a message via the named pipe. if the pipe is empty this call is blocking until a message was + /// received + /// @tparam N capacity of the iox::string + /// @param[in] message the message to receive + /// @return on success a string containing the message, otherwise an error which describes the failure + template + expected receive(iox::string& message) const noexcept; + + /// @brief receives a message via the named pipe. + /// @tparam N capacity of the iox::string + /// @param[in] message the message to receive + /// @param[in] timeout the timeout on how long this method should retry to receive a message + /// @return on success a string containing the message, otherwise an error which describes the failure + template + expected timedReceive(iox::string& message, + const units::Duration& timeout) const noexcept; + private: friend class NamedPipeBuilder; @@ -176,4 +225,7 @@ class NamedPipeBuilder } // namespace iox +#include "detail/named_pipe.inl" + + #endif // IOX_HOOFS_POSIX_IPC_NAMED_PIPE_HPP diff --git a/iceoryx_hoofs/posix/ipc/source/named_pipe.cpp b/iceoryx_hoofs/posix/ipc/source/named_pipe.cpp index bc88f7c0f5..da6212e2e3 100644 --- a/iceoryx_hoofs/posix/ipc/source/named_pipe.cpp +++ b/iceoryx_hoofs/posix/ipc/source/named_pipe.cpp @@ -203,17 +203,7 @@ expected NamedPipe::trySend(const std::string& messa { return err(PosixIpcChannelError::MESSAGE_TOO_LONG); } - - auto result = m_data->sendSemaphore().tryWait(); - IOX_EXPECTS(!result.has_error()); - - if (*result) - { - IOX_DISCARD_RESULT(m_data->messages.push(into>(message))); - IOX_EXPECTS(!m_data->receiveSemaphore().post().has_error()); - return ok(); - } - return err(PosixIpcChannelError::TIMEOUT); + return trySend(into>(message)); } expected NamedPipe::send(const std::string& message) const noexcept @@ -223,11 +213,7 @@ expected NamedPipe::send(const std::string& message) return err(PosixIpcChannelError::MESSAGE_TOO_LONG); } - IOX_EXPECTS(!m_data->sendSemaphore().wait().has_error()); - IOX_DISCARD_RESULT(m_data->messages.push(into>(message))); - IOX_EXPECTS(!m_data->receiveSemaphore().post().has_error()); - - return ok(); + return send(into>(message)); } expected NamedPipe::timedSend(const std::string& message, @@ -238,65 +224,40 @@ expected NamedPipe::timedSend(const std::string& mes return err(PosixIpcChannelError::MESSAGE_TOO_LONG); } - auto result = m_data->sendSemaphore().timedWait(timeout); - IOX_EXPECTS(!result.has_error()); - - if (*result == SemaphoreWaitState::NO_TIMEOUT) - { - IOX_DISCARD_RESULT(m_data->messages.push(into>(message))); - IOX_EXPECTS(!m_data->receiveSemaphore().post().has_error()); - return ok(); - } - return err(PosixIpcChannelError::TIMEOUT); + return timedSend(into>(message), timeout); } expected NamedPipe::receive() const noexcept { - IOX_EXPECTS(!m_data->receiveSemaphore().wait().has_error()); - auto message = m_data->messages.pop(); - if (message.has_value()) + Message_t message; + auto result = receive(message); + if (result.has_error()) { - IOX_EXPECTS(!m_data->sendSemaphore().post().has_error()); - return ok(message->c_str()); + return err(result.error()); } - return err(PosixIpcChannelError::INTERNAL_LOGIC_ERROR); + return ok(message.c_str()); } expected NamedPipe::tryReceive() const noexcept { - auto result = m_data->receiveSemaphore().tryWait(); - IOX_EXPECTS(!result.has_error()); - - if (*result) + Message_t message; + auto result = tryReceive(message); + if (result.has_error()) { - auto message = m_data->messages.pop(); - if (message.has_value()) - { - IOX_EXPECTS(!m_data->sendSemaphore().post().has_error()); - return ok(message->c_str()); - } - return err(PosixIpcChannelError::INTERNAL_LOGIC_ERROR); + return err(result.error()); } - - return err(PosixIpcChannelError::TIMEOUT); + return ok(message.c_str()); } expected NamedPipe::timedReceive(const units::Duration& timeout) const noexcept { - auto result = m_data->receiveSemaphore().timedWait(timeout); - IOX_EXPECTS(!result.has_error()); - - if (*result == SemaphoreWaitState::NO_TIMEOUT) + Message_t message; + auto result = timedReceive(message, timeout); + if (result.has_error()) { - auto message = m_data->messages.pop(); - if (message.has_value()) - { - IOX_EXPECTS(!m_data->sendSemaphore().post().has_error()); - return ok(message->c_str()); - } - return err(PosixIpcChannelError::INTERNAL_LOGIC_ERROR); + return err(result.error()); } - return err(PosixIpcChannelError::TIMEOUT); + return ok(message.c_str()); } expected NamedPipe::NamedPipeData::initialize(const uint32_t maxMsgNumber) noexcept