iceoryx_hoofs/posix_wrapper/posix_call.hpp🔗
Namespaces🔗
Name |
---|
iox building block to easily create free function for logging in a library context |
iox::posix |
iox::posix::internal |
Classes🔗
Name | |
---|---|
struct | iox::posix::PosixCallResult result of a posix call |
class | iox::posix::PosixCallEvaluator class which is created by the verificator to evaluate the result of a posix call |
class | iox::posix::PosixCallVerificator class which verifies the return value of a posix function call |
class | iox::posix::PosixCallBuilder |
Defines🔗
Name | |
---|---|
posixCall(f) Calling a posix function with automated error handling. If the posix function returns void you do not need to use posixCall since it cannot fail, (see: man errno). We use a builder pattern to create a design which sets the usage contract so that it cannot be used in the wrong way. |
Macro Documentation🔗
define posixCall🔗
#define posixCall(
f
)
internal::createPosixCallBuilder(f, #f, __FILE__, __LINE__, __PRETTY_FUNCTION__)
Calling a posix function with automated error handling. If the posix function returns void you do not need to use posixCall since it cannot fail, (see: man errno). We use a builder pattern to create a design which sets the usage contract so that it cannot be used in the wrong way.
iox::posix::posixCall(sem_timedwait)(handle, timeout)
.successReturnValue(0)
.ignoreErrnos(ETIMEDOUT) // can be a comma separated list of errnos
.evaluate()
.and_then([](auto & result){
std::cout << result.value << std::endl; // return value of sem_timedwait
std::cout << result.errno << std::endl; // errno which was set by sem_timedwait
std::cout << result.getHumanReadableErrnum() << std::endl; // get string returned by strerror(errno)
})
.or_else([](auto & result){
std::cout << result.value << std::endl; // return value of sem_timedwait
std::cout << result.errno << std::endl; // errno which was set by sem_timedwait
std::cout << result.getHumanReadableErrnum() << std::endl; // get string returned by strerror(errno)
})
// when your posix call signals failure with one specific return value use
// .failureReturnValue(_) instead of .successReturnValue(_)
// when your posix call signals failure by returning the errno value instead of setting the errno use
// .returnValueMatchesErrno() instead of .successReturnValue(_)
Source code🔗
// Copyright (c) 2021 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_POSIX_WRAPPER_POSIX_CALL_HPP
#define IOX_HOOFS_POSIX_WRAPPER_POSIX_CALL_HPP
#include "iceoryx_hoofs/cxx/algorithm.hpp"
#include "iceoryx_hoofs/cxx/attributes.hpp"
#include "iceoryx_hoofs/cxx/expected.hpp"
#include "iceoryx_hoofs/cxx/string.hpp"
#include <cstdint>
#include <cstring>
namespace iox
{
namespace posix
{
static constexpr uint32_t POSIX_CALL_ERROR_STRING_SIZE = 128U;
static constexpr uint64_t POSIX_CALL_EINTR_REPETITIONS = 5U;
static constexpr int32_t POSIX_CALL_INVALID_ERRNO = -1;
template <typename ReturnType, typename... FunctionArguments>
class PosixCallBuilder;
template <typename T>
struct PosixCallResult
{
PosixCallResult() noexcept = default;
cxx::string<POSIX_CALL_ERROR_STRING_SIZE> getHumanReadableErrnum() const noexcept;
T value{};
int32_t errnum = POSIX_CALL_INVALID_ERRNO;
};
namespace internal
{
template <typename ReturnType, typename... FunctionArguments>
PosixCallBuilder<ReturnType, FunctionArguments...> createPosixCallBuilder(ReturnType (*posixCall)(FunctionArguments...),
const char* posixFunctionName,
const char* file,
const int32_t line,
const char* callingFunction) noexcept;
template <typename ReturnType>
struct PosixCallDetails
{
PosixCallDetails(const char* posixFunctionName, const char* file, int line, const char* callingFunction) noexcept;
const char* posixFunctionName = nullptr;
const char* file = nullptr;
const char* callingFunction = nullptr;
int32_t line = 0;
bool hasSuccess = true;
bool hasIgnoredErrno = false;
bool hasSilentErrno = false;
PosixCallResult<ReturnType> result;
};
} // namespace internal
#define posixCall(f) internal::createPosixCallBuilder(f, #f, __FILE__, __LINE__, __PRETTY_FUNCTION__)
template <typename ReturnType>
class IOX_NO_DISCARD PosixCallEvaluator
{
public:
template <typename... IgnoredErrnos>
PosixCallEvaluator<ReturnType> ignoreErrnos(const IgnoredErrnos... ignoredErrnos) const&& noexcept;
template <typename... SilentErrnos>
PosixCallEvaluator<ReturnType> suppressErrorMessagesForErrnos(const SilentErrnos... silentErrnos) const&& noexcept;
cxx::expected<PosixCallResult<ReturnType>, PosixCallResult<ReturnType>> evaluate() const&& noexcept;
private:
template <typename>
friend class PosixCallVerificator;
explicit PosixCallEvaluator(internal::PosixCallDetails<ReturnType>& details) noexcept;
private:
internal::PosixCallDetails<ReturnType>& m_details;
};
template <typename ReturnType>
class IOX_NO_DISCARD PosixCallVerificator
{
public:
template <typename... SuccessReturnValues>
PosixCallEvaluator<ReturnType> successReturnValue(const SuccessReturnValues... successReturnValues) && noexcept;
template <typename... FailureReturnValues>
PosixCallEvaluator<ReturnType> failureReturnValue(const FailureReturnValues... failureReturnValues) && noexcept;
PosixCallEvaluator<ReturnType> returnValueMatchesErrno() && noexcept;
private:
template <typename, typename...>
friend class PosixCallBuilder;
explicit PosixCallVerificator(internal::PosixCallDetails<ReturnType>& details) noexcept;
private:
internal::PosixCallDetails<ReturnType>& m_details;
};
template <typename ReturnType, typename... FunctionArguments>
class IOX_NO_DISCARD PosixCallBuilder
{
public:
using FunctionType_t = ReturnType (*)(FunctionArguments...);
PosixCallVerificator<ReturnType> operator()(FunctionArguments... arguments) && noexcept;
private:
template <typename ReturnTypeFriend, typename... FunctionArgumentsFriend>
friend PosixCallBuilder<ReturnTypeFriend, FunctionArgumentsFriend...>
internal::createPosixCallBuilder(ReturnTypeFriend (*posixCall)(FunctionArgumentsFriend...),
const char* posixFunctionName,
const char* file,
const int32_t line,
const char* callingFunction) noexcept;
PosixCallBuilder(FunctionType_t posixCall,
const char* posixFunctionName,
const char* file,
const int32_t line,
const char* callingFunction) noexcept;
private:
FunctionType_t m_posixCall = nullptr;
internal::PosixCallDetails<ReturnType> m_details;
};
} // namespace posix
} // namespace iox
#include "iceoryx_hoofs/internal/posix_wrapper/posix_call.inl"
#endif // IOX_HOOFS_POSIX_WRAPPER_POSIX_CALL_HPP
Updated on 2 April 2022 at 16:37:47 CEST