Skip to content
Open
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
17 changes: 17 additions & 0 deletions score/mw/com/design/events_fields/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,23 @@ The same asymmetry shows up in how each side builds the field's event dispatch:
- On the proxy side, the event dispatch (`proxy_event_dispatch_`) is only created when `WithNotifier` is set. Without it
the member stays `nullptr` and the notifier methods are removed at compile time.

The notifier also decides how many sample slots the provider allocates. `numberOfSampleSlots` exists to give
subscribers something to read: the provider sizes the slot pool so all consumers can hold their samples while it
keeps publishing (see the formula in the [configuration readme](../../impl/configuration/README.md)). Without
`WithNotifier` no consumer can ever subscribe (proxy and skeleton are compiled from the same tag pack), so there is
nothing to size. The skeleton only needs two slots for its own `Update()`: one holds the current value, one is
written by the next update. The LoLa binding therefore ignores the configured value for such fields:

| `WithNotifier` | `numberOfSampleSlots` | used slot count |
| -------------- | --------------------- | -------------------------- |
| enabled | configured | as configured |
| enabled | missing | none, startup terminates |
| disabled | missing | 2 |
| disabled | configured | 2, a warning is logged |

Configured `numberOfIpcTracingSlots` come on top of the used slot count in all cases, because tracing holds a
reference to each traced sample until the trace call has completed.

The only combination we actually enforce is a `static_assert` on both `impl::ProxyField` and `impl::SkeletonField`: a
field must have at least one of `WithGetter` or `WithNotifier`. Without one of them the consumer has no way to observe
the value, which makes the field useless. We deliberately do not require a setter, since a read-only field is perfectly normal and the provider always sets the
Expand Down
5 changes: 5 additions & 0 deletions score/mw/com/impl/bindings/lola/skeleton_event_properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@
#define SCORE_MW_COM_IMPL_BINDINGS_LOLA_SKELETON_EVENT_PROPERTIES_H

#include <cstddef>
#include <cstdint>

namespace score::mw::com::impl::lola
{

/// \brief Slot count a field without a notifier uses for its backing event: one slot for the current value, one so
/// Update() can write concurrently.
constexpr std::uint16_t kSlotCountForFieldWithoutNotifier{2U};

struct SkeletonEventProperties
{
std::size_t number_of_slots;
Expand Down
4 changes: 4 additions & 0 deletions score/mw/com/impl/configuration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,10 @@ The properties of a field or an event object on the instance level are:
`numberOfSampleSlots`. I.e. The sum of all `maxSamples` values of all subscribing consumers must not exceed
`numberOfSampleSlots`. Otherwise, the subscribe call will be rejected. However, this check is not ASIL level
overarching. See explanation in the `maxSubscribers` section below.
**Note**: For a field without `WithNotifier` this property is ignored, since no consumer can subscribe to it.
The provider always uses 2 slots there: one for the current value and one so `Update()` can write concurrently.
If a value is configured anyway, a warning is logged. See the
[events and fields design](../../design/events_fields/README.md) for details.
- `maxSubscribers`: (mandatory on provider side) - how many consumers are allowed to subscribe to this event or field.
This number is the combined number of `QM` and `ASIL-B` consumers.
**Note**: The maximum number of subscribers can't currently be supervised ASIL level **overarching**. I.e. in case of
Expand Down
9 changes: 9 additions & 0 deletions score/mw/com/impl/field_tags.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef SCORE_MW_COM_IMPL_FIELD_TAGS_H
#define SCORE_MW_COM_IMPL_FIELD_TAGS_H

#include <cstdint>
#include <type_traits>

namespace score::mw::com::impl
Expand All @@ -32,6 +33,14 @@ struct WithNotifier
{
};

/// \brief Runtime form of the WithNotifier tag, for places the tag pack cannot reach (e.g. the binding
/// factories).
enum class FieldNotifier : std::uint8_t
{
kEnabled = 0U,
kDisabled
};

template <typename TargetType, typename... Tags>
struct contains_type : std::disjunction<std::is_same<TargetType, Tags>...>
{
Expand Down
5 changes: 5 additions & 0 deletions score/mw/com/impl/plumbing/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ cc_library(
"//score/mw/com/impl/plumbing:__subpackages__",
],
deps = [
"//score/mw/com/impl:field_tags",
"//score/mw/com/impl:instance_identifier",
"//score/mw/com/impl:skeleton_base",
"@score_baselibs//score/language/futurecpp",
Expand Down Expand Up @@ -408,6 +409,7 @@ cc_library(
deps = [
":i_skeleton_field_binding_factory",
":skeleton_service_element_binding_factory_impl",
"//score/mw/com/impl:field_tags",
"@score_baselibs//score/language/futurecpp",
],
)
Expand Down Expand Up @@ -509,6 +511,7 @@ cc_library(
deps = [
"skeleton_field_binding_factory_impl",
":i_skeleton_field_binding_factory",
"//score/mw/com/impl:field_tags",
"@score_baselibs//score/language/futurecpp",
],
)
Expand Down Expand Up @@ -614,6 +617,7 @@ cc_library(
],
deps = [
":i_skeleton_field_binding_factory",
"//score/mw/com/impl:field_tags",
"@googletest//:gtest",
],
)
Expand Down Expand Up @@ -845,6 +849,7 @@ cc_unit_test(
"//score/mw/com/impl/bindings/mock_binding",
"//score/mw/com/impl/configuration/test:configuration_store",
"//score/mw/com/impl/test:dummy_instance_identifier_builder",
"@score_baselibs//score/mw/log:recorder_mock",
],
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef SCORE_MW_COM_IMPL_PLUMBING_I_SKELETON_FIELD_BINDING_FACTORY_H
#define SCORE_MW_COM_IMPL_PLUMBING_I_SKELETON_FIELD_BINDING_FACTORY_H

#include "score/mw/com/impl/field_tags.h"
#include "score/mw/com/impl/handle_type.h"
#include "score/mw/com/impl/instance_identifier.h"
#include "score/mw/com/impl/skeleton_base.h"
Expand Down Expand Up @@ -44,10 +45,12 @@ class ISkeletonFieldBindingFactory
/// \param identifier The instance identifier containing the binding information.
/// \param parent A reference to the Skeleton which owns this event.
/// \param field_name The binding unspecific name of the field inside the skeleton denoted by instance identifier.
/// \param field_notifier An enum indicating whether the field was declared with WithNotifier or not.
/// \return An instance of SkeletonEventBinding or nullptr in case of an error.
virtual auto CreateEventBinding(const InstanceIdentifier& identifier,
SkeletonBinding& parent_binding,
const std::string_view field_name) noexcept
const std::string_view field_name,
const FieldNotifier field_notifier) noexcept
-> std::unique_ptr<SkeletonEventBinding<SampleType>> = 0;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,8 @@ auto SkeletonEventBindingFactoryImpl<SampleType>::Create(const InstanceIdentifie
const std::string_view event_name) noexcept
-> std::unique_ptr<SkeletonEventBinding<SampleType>>
{
return CreateSkeletonEventOrField<SkeletonEventBinding<SampleType>,
lola::SkeletonEvent<SampleType>,
ServiceElementType::EVENT>(identifier, parent_binding, event_name);
return CreateSkeletonEvent<SkeletonEventBinding<SampleType>, lola::SkeletonEvent<SampleType>>(
identifier, parent_binding, event_name);
}

} // namespace score::mw::com::impl
Expand Down
6 changes: 4 additions & 2 deletions score/mw/com/impl/plumbing/skeleton_field_binding_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "score/mw/com/impl/bindings/lola/element_fq_id.h"
#include "score/mw/com/impl/bindings/lola/skeleton_event.h"
#include "score/mw/com/impl/configuration/service_type_deployment.h"
#include "score/mw/com/impl/field_tags.h"
#include "score/mw/com/impl/instance_identifier.h"
#include "score/mw/com/impl/plumbing/i_skeleton_field_binding_factory.h"
#include "score/mw/com/impl/plumbing/skeleton_field_binding_factory_impl.h"
Expand All @@ -39,9 +40,10 @@ class SkeletonFieldBindingFactory final
/// \brief See documentation in ISkeletonFieldBindingFactory.
static std::unique_ptr<SkeletonEventBinding<SampleType>> CreateEventBinding(const InstanceIdentifier& identifier,
SkeletonBinding& parent_binding,
const std::string_view field_name)
const std::string_view field_name,
const FieldNotifier field_notifier)
{
return instance().CreateEventBinding(identifier, parent_binding, field_name);
return instance().CreateEventBinding(identifier, parent_binding, field_name, field_notifier);
}

/// \brief Inject a mock ISkeletonFieldBindingFactory. If a mock is injected, then all calls on
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@

#include "score/mw/com/impl/bindings/lola/element_fq_id.h"
#include "score/mw/com/impl/bindings/lola/skeleton_event.h"
#include "score/mw/com/impl/bindings/lola/skeleton_event_properties.h"
#include "score/mw/com/impl/field_tags.h"
#include "score/mw/com/impl/instance_identifier.h"
#include "score/mw/com/impl/plumbing/i_skeleton_field_binding_factory.h"
#include "score/mw/com/impl/plumbing/skeleton_service_element_binding_factory_impl.h"
#include "score/mw/com/impl/skeleton_base.h"
#include "score/mw/com/impl/skeleton_event_binding.h"

#include <cstdint>
#include <memory>
#include <optional>
#include <string_view>

namespace score::mw::com::impl
Expand All @@ -36,7 +40,8 @@ class SkeletonFieldBindingFactoryImpl : public ISkeletonFieldBindingFactory<Samp
std::unique_ptr<SkeletonEventBinding<SampleType>> CreateEventBinding(
const InstanceIdentifier& identifier,
SkeletonBinding& parent_binding,
const std::string_view field_name) noexcept override;
const std::string_view field_name,
const FieldNotifier field_notifier) noexcept override;
};

template <typename SampleType>
Expand All @@ -50,12 +55,16 @@ template <typename SampleType>
// coverity[autosar_cpp14_a15_5_3_violation : FALSE]
auto SkeletonFieldBindingFactoryImpl<SampleType>::CreateEventBinding(const InstanceIdentifier& identifier,
SkeletonBinding& parent_binding,
const std::string_view field_name) noexcept
const std::string_view field_name,
const FieldNotifier field_notifier) noexcept
-> std::unique_ptr<SkeletonEventBinding<SampleType>>
{
return CreateSkeletonEventOrField<SkeletonEventBinding<SampleType>,
lola::SkeletonEvent<SampleType>,
ServiceElementType::FIELD>(identifier, parent_binding, field_name);
const std::optional<LolaEventInstanceDeployment::SampleSlotCountType> slot_count_override =
field_notifier == FieldNotifier::kDisabled
? std::optional<LolaEventInstanceDeployment::SampleSlotCountType>{lola::kSlotCountForFieldWithoutNotifier}
: std::nullopt;
return CreateSkeletonField<SkeletonEventBinding<SampleType>, lola::SkeletonEvent<SampleType>>(
identifier, parent_binding, field_name, slot_count_override);
}

} // namespace score::mw::com::impl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef SCORE_MW_COM_IMPL_PLUMBING_SKELETON_FIELD_BINDING_FACTORY_MOCK_H
#define SCORE_MW_COM_IMPL_PLUMBING_SKELETON_FIELD_BINDING_FACTORY_MOCK_H

#include "score/mw/com/impl/field_tags.h"
#include "score/mw/com/impl/plumbing/i_skeleton_field_binding_factory.h"

#include <gmock/gmock.h>
Expand All @@ -26,7 +27,7 @@ class SkeletonFieldBindingFactoryMock : public ISkeletonFieldBindingFactory<Samp
public:
MOCK_METHOD(std::unique_ptr<SkeletonEventBinding<SampleType>>,
CreateEventBinding,
(const InstanceIdentifier&, SkeletonBinding&, const std::string_view),
(const InstanceIdentifier&, SkeletonBinding&, const std::string_view, const FieldNotifier),
(noexcept, override));
};

Expand Down
Loading
Loading