Skip to content

Commit

Permalink
Merge pull request #2173 from lucabart97/iox-1693-iox-string-namedpipe
Browse files Browse the repository at this point in the history
iox-#1693 support for iox::string in NamedPipe
  • Loading branch information
elBoberido authored Feb 4, 2024
2 parents 7135c57 + da6cc54 commit 80bbdf9
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 57 deletions.
2 changes: 2 additions & 0 deletions doc/website/release-notes/iceoryx-unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:**

Expand Down
128 changes: 128 additions & 0 deletions iceoryx_hoofs/posix/ipc/include/iox/detail/named_pipe.inl
Original file line number Diff line number Diff line change
@@ -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 <uint64_t N>
expected<void, PosixIpcChannelError> NamedPipe::trySend(const iox::string<N>& 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 <uint64_t N>
expected<void, PosixIpcChannelError> NamedPipe::send(const iox::string<N>& 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 <uint64_t N>
expected<void, PosixIpcChannelError> NamedPipe::timedSend(const iox::string<N>& 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 <uint64_t N>
expected<void, PosixIpcChannelError> NamedPipe::receive(iox::string<N>& 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 <uint64_t N>
expected<void, PosixIpcChannelError> NamedPipe::tryReceive(iox::string<N>& 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 <uint64_t N>
expected<void, PosixIpcChannelError> NamedPipe::timedReceive(iox::string<N>& 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
52 changes: 52 additions & 0 deletions iceoryx_hoofs/posix/ipc/include/iox/named_pipe.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,55 @@ class NamedPipe
/// @return on success a string containing the message, otherwise an error which describes the failure
expected<std::string, PosixIpcChannelError> 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 <uint64_t N>
expected<void, PosixIpcChannelError> trySend(const iox::string<N>& 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 <uint64_t N>
expected<void, PosixIpcChannelError> send(const iox::string<N>& 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 <uint64_t N>
expected<void, PosixIpcChannelError> timedSend(const iox::string<N>& 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 <uint64_t N>
expected<void, PosixIpcChannelError> tryReceive(iox::string<N>& 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 <uint64_t N>
expected<void, PosixIpcChannelError> receive(iox::string<N>& 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 <uint64_t N>
expected<void, PosixIpcChannelError> timedReceive(iox::string<N>& message,
const units::Duration& timeout) const noexcept;

private:
friend class NamedPipeBuilder;

Expand Down Expand Up @@ -176,4 +225,7 @@ class NamedPipeBuilder

} // namespace iox

#include "detail/named_pipe.inl"


#endif // IOX_HOOFS_POSIX_IPC_NAMED_PIPE_HPP
75 changes: 18 additions & 57 deletions iceoryx_hoofs/posix/ipc/source/named_pipe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,17 +203,7 @@ expected<void, PosixIpcChannelError> 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<lossy<Message_t>>(message)));
IOX_EXPECTS(!m_data->receiveSemaphore().post().has_error());
return ok();
}
return err(PosixIpcChannelError::TIMEOUT);
return trySend(into<lossy<Message_t>>(message));
}

expected<void, PosixIpcChannelError> NamedPipe::send(const std::string& message) const noexcept
Expand All @@ -223,11 +213,7 @@ expected<void, PosixIpcChannelError> 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<lossy<Message_t>>(message)));
IOX_EXPECTS(!m_data->receiveSemaphore().post().has_error());

return ok();
return send(into<lossy<Message_t>>(message));
}

expected<void, PosixIpcChannelError> NamedPipe::timedSend(const std::string& message,
Expand All @@ -238,65 +224,40 @@ expected<void, PosixIpcChannelError> 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<lossy<Message_t>>(message)));
IOX_EXPECTS(!m_data->receiveSemaphore().post().has_error());
return ok();
}
return err(PosixIpcChannelError::TIMEOUT);
return timedSend(into<lossy<Message_t>>(message), timeout);
}

expected<std::string, PosixIpcChannelError> 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<std::string>(message->c_str());
return err(result.error());
}
return err(PosixIpcChannelError::INTERNAL_LOGIC_ERROR);
return ok<std::string>(message.c_str());
}

expected<std::string, PosixIpcChannelError> 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<std::string>(message->c_str());
}
return err(PosixIpcChannelError::INTERNAL_LOGIC_ERROR);
return err(result.error());
}

return err(PosixIpcChannelError::TIMEOUT);
return ok<std::string>(message.c_str());
}

expected<std::string, PosixIpcChannelError> 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<std::string>(message->c_str());
}
return err(PosixIpcChannelError::INTERNAL_LOGIC_ERROR);
return err(result.error());
}
return err(PosixIpcChannelError::TIMEOUT);
return ok<std::string>(message.c_str());
}

expected<void, PosixIpcChannelError> NamedPipe::NamedPipeData::initialize(const uint32_t maxMsgNumber) noexcept
Expand Down

0 comments on commit 80bbdf9

Please sign in to comment.