Skip to content

Commit

Permalink
libcyphal::config (#408)
Browse files Browse the repository at this point in the history
- Now sending uses stack for serialization of small
messages/request/responses, and PMR otherwise (#400)
- Introduced `libcyphal::config`
- Fix for #398 

Also:
- eliminated deprecated NOSONAR cpp:S4963 - I disabled the rule at Sonar
  • Loading branch information
serges147 authored Dec 11, 2024
1 parent 6f801fc commit 914d85d
Show file tree
Hide file tree
Showing 45 changed files with 692 additions and 267 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,7 @@ class EpollSingleThreadedExecutor final : public libcyphal::platform::SingleThre
using Base = SingleThreadedExecutor;
using Self = EpollSingleThreadedExecutor;

/// No Sonar cpp:S4963 b/c `AwaitableNode` supports move operation.
///
class AwaitableNode final : public CallbackNode // NOSONAR cpp:S4963
class AwaitableNode final : public CallbackNode
{
public:
AwaitableNode(Self& executor, Callback::Function&& function)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,7 @@ class PollSingleThreadedExecutor final : public libcyphal::platform::SingleThrea
DoubleLinkedNode* next_node;
};

/// No Sonar cpp:S4963 b/c `AwaitableNode` supports move operation.
///
class AwaitableNode final : public CallbackNode, public DoubleLinkedNode // NOSONAR cpp:S4963
class AwaitableNode final : public CallbackNode, public DoubleLinkedNode
{
public:
AwaitableNode(Self& executor, Callback::Function&& function, DoubleLinkedNode& origin_node)
Expand Down
7 changes: 4 additions & 3 deletions include/libcyphal/application/node/get_info_provider.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ namespace node
///
/// Internally, it uses the 'GetInfo' service server to handle incoming requests.
///
/// No Sonar cpp:S4963 'The "Rule-of-Zero" should be followed'
/// b/c we do directly handle resources here (namely capturing of `this` in the request callback).
/// No Sonar cpp:S3624 "Customize this class' destructor to participate in resource management."
/// We need custom move constructor to reset up the request callback,
/// but at the destructor level, we don't need to do anything.
///
class GetInfoProvider final // NOSONAR cpp:S4963
class GetInfoProvider final // NOSONAR cpp:S3624
{
using Service = uavcan::node::GetInfo_1_0;

Expand Down
14 changes: 7 additions & 7 deletions include/libcyphal/application/node/heartbeat_producer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#ifndef LIBCYPHAL_APPLICATION_NODE_HEARTBEAT_PRODUCER_HPP_INCLUDED
#define LIBCYPHAL_APPLICATION_NODE_HEARTBEAT_PRODUCER_HPP_INCLUDED

#include "libcyphal/config.hpp"
#include "libcyphal/executor.hpp"
#include "libcyphal/presentation/presentation.hpp"
#include "libcyphal/presentation/publisher.hpp"
Expand Down Expand Up @@ -33,10 +34,11 @@ namespace node
///
/// Internally, it uses the 'Heartbeat' message publisher to periodically publish heartbeat messages.
///
/// No Sonar cpp:S4963 'The "Rule-of-Zero" should be followed'
/// b/c we do directly handle resources here (namely capturing of `this` in the periodic callback).
/// No Sonar cpp:S3624 "Customize this class' destructor to participate in resource management."
/// We need custom move constructor to reset up the publishing callback,
/// but at the destructor level, we don't need to do anything.
///
class HeartbeatProducer final // NOSONAR cpp:S4963
class HeartbeatProducer final // NOSONAR cpp:S3624
{
public:
/// @brief Defines the message type for the Heartbeat.
Expand Down Expand Up @@ -110,10 +112,8 @@ class HeartbeatProducer final // NOSONAR cpp:S4963

/// @brief Defines signature of the heartbeat update callback function.
///
/// The size of the function is arbitrary (4 pointers), but should be enough for simple lambdas.
///
static constexpr std::size_t FunctionSize = sizeof(void*) * 4;
using Function = cetl::pmr::function<void(const Arg& arg), FunctionSize>;
static constexpr auto FunctionSize = config::Application::Node::HeartbeatProducer_UpdateCallback_FunctionSize();
using Function = cetl::pmr::function<void(const Arg& arg), FunctionSize>;
};

/// @brief Sets the message update callback for the heartbeat.
Expand Down
7 changes: 4 additions & 3 deletions include/libcyphal/application/node/registry_provider.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ namespace node
///
/// Internally, it uses the registry 'List' and 'Access' service servers to handle incoming requests.
///
/// No Sonar cpp:S4963 'The "Rule-of-Zero" should be followed'
/// b/c we do directly handle resources here (namely capturing of `this` in the request callback).
/// No Sonar cpp:S3624 "Customize this class' destructor to participate in resource management."
/// We need custom move constructor to reset up the request callback,
/// but at the destructor level, we don't need to do anything.
///
class RegistryProvider final // NOSONAR cpp:S4963
class RegistryProvider final // NOSONAR cpp:S3624
{
using ListService = uavcan::_register::List_1_0;
using AccessService = uavcan::_register::Access_1_0;
Expand Down
4 changes: 1 addition & 3 deletions include/libcyphal/application/registry/register.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ enum class SetError : std::uint8_t

/// Defines interface for a register.
///
/// NOSONAR cpp:S4963 for below `class IRegister` - protected destructor is necessary.
///
class IRegister : public cavl::Node<IRegister> // NOSONAR cpp:S4963
class IRegister : public cavl::Node<IRegister>
{
// 1AD1885B-954B-48CF-BAC4-FA0A251D3FC0
// clang-format off
Expand Down
8 changes: 3 additions & 5 deletions include/libcyphal/common/cavl/cavl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,9 @@ class Tree;
/// The size of this type is 4x pointer size (16 bytes on a 32-bit platform).
///
/// No Sonar cpp:S1448 b/c this is the main node entity without public members - maintainability is not a concern here.
/// No Sonar cpp:S4963 b/c `Node` supports move operation.
///
template <typename Derived>
class Node // NOSONAR cpp:S1448 cpp:S4963
class Node // NOSONAR cpp:S1448
{
// Polyfill for C++17's std::invoke_result_t.
template <typename F, typename... Args>
Expand Down Expand Up @@ -954,8 +953,7 @@ class Tree final // NOSONAR cpp:S3624
/// the same call stack) we may occasionally fail to detect a bona fide case of a race condition, but this is
/// acceptable because the purpose of this feature is to provide a mere best-effort data race detection.
///
/// No Sonar cpp:S4963 b/c of the RAII pattern.
class TraversalIndicatorUpdater final // NOSONAR cpp:S4963
class TraversalIndicatorUpdater final
{
public:
explicit TraversalIndicatorUpdater(const Tree& sup) noexcept
Expand Down Expand Up @@ -994,7 +992,7 @@ class Tree final // NOSONAR cpp:S3624
// including the root node whos `up` points to this origin node (see `isRoot` method).
Node<Derived> origin_node_{};

// No Sonar cpp:S4963 b/c of implicit modification by the `TraversalIndicatorUpdater` RAII class,
// No Sonar cpp:S3687 b/c of implicit modification by the `TraversalIndicatorUpdater` RAII class,
// even for `const` instance of the `Tree` class (hence the `mutable volatile` keywords).
mutable volatile bool traversal_in_progress_ = false; // NOSONAR cpp:S3687
};
Expand Down
190 changes: 190 additions & 0 deletions include/libcyphal/config.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
/// @copyright
/// Copyright (C) OpenCyphal Development Team <opencyphal.org>
/// Copyright Amazon.com Inc. or its affiliates.
/// SPDX-License-Identifier: MIT

#ifndef LIBCYPHAL_CONFIG_HPP_INCLUDED
#define LIBCYPHAL_CONFIG_HPP_INCLUDED

#include <cstddef>

namespace libcyphal
{

// All below NOSONAR cpp:S799 "Rename this identifier to be shorter or equal to 31 characters."
// are intentional and are used to keep the names consistent with the rest of the codebase.
// F.e. `IExecutor_Callback_FunctionMaxSize` is consistent with `IExecutor::Callback::FunctionMaxSize`.

/// Defines various configuration parameters of libcyphal.
///
/// All methods are `static constexpr` - they are evaluated at compile time.
///
/// Nolint b/c this is the main purpose of this file - define various constants.
/// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers)
///
struct Config
{
/// Defines max footprint of a callback function in use by the executor.
///
static constexpr std::size_t IExecutor_Callback_FunctionMaxSize() // NOSONAR cpp:S799
{
return sizeof(void*) * 8;
}

/// Defines footprint size reserved for a callback implementation.
/// The actual max footprint for the callback implementation is `sizeof(IExecutor::Function)` bigger,
/// and it depends on `Cfg_IExecutor_Callback_FunctionMaxSize`.
///
static constexpr std::size_t IExecutor_Callback_ReserveSize() // NOSONAR cpp:S799
{
/// Size is chosen arbitrary, but it should be enough to store any lambda or function pointer.
return sizeof(void*) * 16;
}

/// Defines various configuration parameters for the application layer.
///
struct Application
{
struct Node
{
/// Defines max footprint of a callback function in use by the heartbeat producer.
///
static constexpr std::size_t HeartbeatProducer_UpdateCallback_FunctionSize() // NOSONAR cpp:S799
{
/// Size is chosen arbitrary, but it should be enough to store any lambda or function pointer.
return sizeof(void*) * 4;
}

}; // Node

}; // Application

/// Defines various configuration parameters for the presentation layer.
///
struct Presentation
{
/// Defines max footprint of a callback function in use by the RPC client response promise.
///
static constexpr std::size_t ResponsePromiseBase_Callback_FunctionSize() // NOSONAR cpp:S799
{
/// Size is chosen arbitrary, but it should be enough to store any lambda or function pointer.
return sizeof(void*) * 4;
}

/// Defines max footprint of a callback function in use by the RPC server response continuation.
///
static constexpr std::size_t ServerBase_ContinuationImpl_FunctionMaxSize() // NOSONAR cpp:S799
{
/// Size is chosen arbitrary, but it should be enough to store any lambda or function pointer.
return sizeof(void*) * 5;
}

/// Defines max footprint of a callback function in use by the RPC server request notification.
///
static constexpr std::size_t ServerBase_OnRequestCallback_FunctionMaxSize() // NOSONAR cpp:S799
{
/// Size is chosen arbitrary, but it should be enough to store any lambda or function pointer.
return sizeof(void*) * 5;
}

/// Defines the size serialization/deserialization payload buffer which is considered as a small one,
/// and therefore could be used with stack buffer. Any payload larger than this size will be PMR allocated.
///
/// Setting it to 0 will force all payload buffers to be PMR allocated (except zero-sized).
///
static constexpr std::size_t SmallPayloadSize()
{
/// Size is chosen arbitrary - as compromise between stack and PMR allocation.
return 256;
}

/// Defines max footprint of a callback function in use by the message subscriber receive notification.
///
static constexpr std::size_t Subscriber_OnReceiveCallback_FunctionMaxSize() // NOSONAR cpp:S799
{
/// Size is chosen arbitrary, but it should be enough to store any lambda or function pointer.
return sizeof(void*) * 4;
}
};

/// Defines various configuration parameters for the transport layer.
///
struct Transport
{
/// Defines max footprint of a callback function in use by the message RX session notification.
/// Size is chosen arbitrary, but it should be enough to store any lambda or function pointer.
///
static constexpr std::size_t IMessageRxSession_OnReceiveCallback_FunctionMaxSize() // NOSONAR cpp:S799
{
/// Size is chosen arbitrary, but it should be enough to store any lambda or function pointer.
return sizeof(void*) * 4;
}

/// Defines max footprint of a callback function in use by the service RX session notification.
/// Size is chosen arbitrary, but it should be enough to store any lambda or function pointer.
///
static constexpr std::size_t ISvcRxSession_OnReceiveCallback_FunctionMaxSize() // NOSONAR cpp:S799
{
/// Size is chosen arbitrary, but it should be enough to store any lambda or function pointer.
return sizeof(void*) * 4;
}

/// Defines max footprint of a platform-specific error implementation.
///
static constexpr std::size_t PlatformErrorMaxSize()
{
/// Size is chosen arbitrary, but it should be enough to store simple implementation.
return sizeof(void*) * 3;
}

/// Defines max footprint of a storage implementation used by the scattered buffer.
///
static constexpr std::size_t ScatteredBuffer_StorageVariantFootprint() // NOSONAR cpp:S799
{
/// Size is chosen arbitrary, but it should be enough to store any implementation.
return sizeof(void*) * 8;
}

/// Defines various configuration parameters for the CAN transport sublayer.
///
struct Can
{
/// Defines max footprint of a callback function in use by the CAN transport transient error handler.
///
static constexpr std::size_t ICanTransport_TransientErrorHandlerMaxSize() // NOSONAR cpp:S799
{
/// Size is chosen arbitrary, but it should be enough to store simple lambda or function pointer.
return sizeof(void*) * 3;
}

}; // Can

/// Defines various configuration parameters for the UDO transport sublayer.
///
struct Udp
{
/// Defines max footprint of a callback function in use by the UDP transport transient error handler.
///
static constexpr std::size_t IUdpTransport_TransientErrorHandlerMaxSize() // NOSONAR cpp:S799
{
/// Size is chosen arbitrary, but it should be enough to store simple lambda or function pointer.
return sizeof(void*) * 3;
}

}; // Udp

}; // Transport

}; // Config

// NOLINTEND(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers)

#ifdef LIBCYPHAL_CONFIG
using config = LIBCYPHAL_CONFIG;
#else
using config = Config;
#endif

} // namespace libcyphal

#endif // LIBCYPHAL_CONFIG_HPP_INCLUDED
17 changes: 9 additions & 8 deletions include/libcyphal/executor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#ifndef LIBCYPHAL_EXECUTOR_HPP_INCLUDED
#define LIBCYPHAL_EXECUTOR_HPP_INCLUDED

#include "config.hpp"
#include "time_provider.hpp"
#include "types.hpp"

Expand All @@ -23,7 +24,7 @@ namespace libcyphal

/// @brief Defines an abstract interface for a callback executor.
///
class IExecutor : public ITimeProvider
class IExecutor : public cetl::rtti::rtti, public ITimeProvider
{
// EBAF7312-5CFE-45F5-89FF-D9B9FE45F8EB
// clang-format off
Expand Down Expand Up @@ -71,7 +72,7 @@ class IExecutor : public ITimeProvider
///
/// Size is chosen arbitrary, but it should be enough to store any lambda or function pointer.
///
static constexpr std::size_t FunctionMaxSize = sizeof(void*) * 8;
static constexpr auto FunctionMaxSize = config::IExecutor_Callback_FunctionMaxSize();

/// @brief Defines type of callback `Function` single argument.
///
Expand Down Expand Up @@ -103,9 +104,9 @@ class IExecutor : public ITimeProvider
///
/// Size is chosen arbitrary, but it should be enough to store any callback implementation.
///
static constexpr std::size_t MaxSize = (sizeof(void*) * 16) + sizeof(Function);
static constexpr auto MaxSize = config::IExecutor_Callback_ReserveSize() + sizeof(Function);

class Interface
class Interface : public rtti
{
// 5E16E6BC-C7EB-42EC-8A98-06189C2F0349
// clang-format off
Expand Down Expand Up @@ -139,13 +140,13 @@ class IExecutor : public ITimeProvider
}

// No Sonar `cpp:S5008` and `cpp:S5356` b/c they are unavoidable - RTTI integration.
CETL_NODISCARD void* _cast_(const cetl::type_id& id) & noexcept // NOSONAR cpp:S5008
CETL_NODISCARD void* _cast_(const cetl::type_id& id) & noexcept override // NOSONAR cpp:S5008
{
return (id == _get_type_id_()) ? this : nullptr; // NOSONAR cpp:S5356
}

// No Sonar `cpp:S5008` and `cpp:S5356` b/c they are unavoidable - RTTI integration.
CETL_NODISCARD const void* _cast_(const cetl::type_id& id) const& noexcept // NOSONAR cpp:S5008
CETL_NODISCARD const void* _cast_(const cetl::type_id& id) const& noexcept override // NOSONAR cpp:S5008
{
return (id == _get_type_id_()) ? this : nullptr; // NOSONAR cpp:S5356
}
Expand Down Expand Up @@ -240,13 +241,13 @@ class IExecutor : public ITimeProvider
}

// No Sonar `cpp:S5008` and `cpp:S5356` b/c they are unavoidable - RTTI integration.
CETL_NODISCARD virtual void* _cast_(const cetl::type_id& id) & noexcept // NOSONAR cpp:S5008
CETL_NODISCARD void* _cast_(const cetl::type_id& id) & noexcept override // NOSONAR cpp:S5008
{
return (id == _get_type_id_()) ? this : nullptr; // NOSONAR cpp:S5356
}

// No Sonar `cpp:S5008` and `cpp:S5356` b/c they are unavoidable - RTTI integration.
CETL_NODISCARD virtual const void* _cast_(const cetl::type_id& id) const& noexcept // NOSONAR cpp:S5008
CETL_NODISCARD const void* _cast_(const cetl::type_id& id) const& noexcept override // NOSONAR cpp:S5008
{
return (id == _get_type_id_()) ? this : nullptr; // NOSONAR cpp:S5356
}
Expand Down
Loading

0 comments on commit 914d85d

Please sign in to comment.