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
5 changes: 5 additions & 0 deletions docs/sphinx/index.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Communication Middleware (mw::com)
==================================

.. image:: _static/lola_logo.svg
:alt: LoLa logo
:align: center
:width: 560

Welcome to the documentation for Communication Middleware (mw::com),
including the LoLa (Low Latency) implementation and Message Passing library.

Expand Down
4 changes: 4 additions & 0 deletions score/mw/com/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ The notion of a `technical binding` also comes from the `ara::com` AUTOSAR stand
It is even common, that implementations of the `ara::com` standard come up with several different `technical binding`s
(e.g. one for local and one for network communication).

## LoLa IPC overview

![LoLa IPC overview](./design/events_fields/Lola_IPC_Overview.svg)

## Documentation for users

If you are an adaptive application developer in the IPNEXT project, and you want to use `mw::com` to do local
Expand Down
36 changes: 36 additions & 0 deletions score/mw/com/impl/bindings/lola/proxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,16 @@ void Proxy::UnregisterEventBinding(const std::string_view service_element_name)
// This is a false positive, we don't use auto here
// coverity[autosar_cpp14_a8_5_3_violation : FALSE]
std::lock_guard lock{proxy_event_registration_mutex_};
// During destruction the event_bindings_ map would be cleared and then the EventBindingRegistrationGuard would call
// UnregisterEventBinding. In that case, the event_bindings_ map would be empty and we would ignore the
// UnregisterEventBinding call. We added this check to avoid logging warnings about unregistering event bindings
// that were never registered during destruction.
if (event_bindings_.size() == 0U)
{
score::mw::log::LogDebug("lola")
<< "UnregisterEventBinding called but there are no registered event bindings. Ignoring.";
return;
}
const auto number_of_elements_removed = event_bindings_.erase(service_element_name);
if (number_of_elements_removed == 0U)
{
Expand Down Expand Up @@ -929,4 +939,30 @@ void Proxy::RegisterMethod(const UniqueMethodIdentifier method_id, ProxyMethod&
SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE(was_inserted, "Method IDs must be unique!");
}

<<<<<<< Updated upstream
void Proxy::UnregisterMethod(const UniqueMethodIdentifier method_id) noexcept
{
std::lock_guard lock{proxy_method_registration_mutex_};
const auto number_of_elements_removed = proxy_methods_.erase(method_id);
if (number_of_elements_removed == 0U)
{
score::mw::log::LogWarn("lola") << "UnregisterMethod with method ID that was never registered. Ignoring.";
=======
void Proxy::ShutdownBinding() noexcept
{
// this causes the destruction of the FindServiceGuard which calls StopFindService so we prevent any future
// notifications from servicediscovery thread.
find_service_guard_.reset();
{
std::lock_guard lock{proxy_event_registration_mutex_};
event_bindings_.clear();
is_service_instance_available_ = false;
}
{
std::lock_guard lock{proxy_method_registration_mutex_};
proxy_methods_.clear();
>>>>>>> Stashed changes
}
}

} // namespace score::mw::com::impl::lola
3 changes: 3 additions & 0 deletions score/mw/com/impl/bindings/lola/proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ class Proxy : public ProxyBinding
}

void RegisterMethod(const UniqueMethodIdentifier method_id, ProxyMethod& proxy_method) noexcept;
void UnregisterMethod(const UniqueMethodIdentifier method_id) noexcept;

void ShutdownBinding() noexcept override;

private:
static std::atomic<ProxyInstanceIdentifier::ProxyInstanceCounter> current_proxy_instance_counter_;
Expand Down
5 changes: 0 additions & 5 deletions score/mw/com/impl/bindings/lola/proxy_event_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@ ProxyEventCommon::ProxyEventCommon(Proxy& parent, const ElementFqId element_fq_i
{
}

ProxyEventCommon::~ProxyEventCommon()
{
Unsubscribe();
}

Result<void> ProxyEventCommon::Subscribe(const std::size_t max_sample_count)
{
std::stringstream sstream{};
Expand Down
2 changes: 1 addition & 1 deletion score/mw/com/impl/bindings/lola/proxy_event_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class ProxyEventCommon final

public:
ProxyEventCommon(Proxy& parent, const ElementFqId element_fq_id, const std::string_view event_name);
~ProxyEventCommon();
~ProxyEventCommon() = default;

ProxyEventCommon(const ProxyEventCommon&) = delete;
ProxyEventCommon(ProxyEventCommon&&) noexcept = delete;
Expand Down
5 changes: 5 additions & 0 deletions score/mw/com/impl/bindings/lola/proxy_method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ ProxyMethod::ProxyMethod(Proxy& proxy,
proxy.RegisterMethod(proxy_method_instance_identifier_.unique_method_identifier, *this);
}

ProxyMethod::~ProxyMethod() noexcept
{
proxy_.UnregisterMethod(proxy_method_instance_identifier_.unique_method_identifier);
}

score::Result<score::cpp::span<std::byte>> ProxyMethod::GetInArgsBuffer(std::size_t queue_position)
{
if (!is_subscribed_)
Expand Down
2 changes: 2 additions & 0 deletions score/mw/com/impl/bindings/lola/proxy_method.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class ProxyMethod : public ProxyMethodBinding
ProxyMethodInstanceIdentifier proxy_method_instance_identifier,
const TypeErasedCallQueue::TypeErasedElementInfo type_erased_element_info);

~ProxyMethod() noexcept override;

/// \brief Allocates storage for the in-arguments of a method call at the given queue position.
///
/// See ProxyMethodBinding for details
Expand Down
16 changes: 16 additions & 0 deletions score/mw/com/impl/proxy_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,22 @@ Result<void> ProxyBase::SetupMethods()
return {};
}

void ProxyBase::Unsubscribe() noexcept
{
if (proxy_binding_ != nullptr)
{
proxy_binding_->ShutdownBinding();
}
for (auto& event : events_)
{
event.second.get().Unsubscribe();
}
for (auto& field : fields_)
{
field.second.get().Unsubscribe();
}
}

ProxyBaseView::ProxyBaseView(ProxyBase& proxy_base) noexcept : proxy_base_(proxy_base) {}

ProxyBinding* ProxyBaseView::GetBinding() noexcept
Expand Down
2 changes: 2 additions & 0 deletions score/mw/com/impl/proxy_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ class ProxyBase
*/
const HandleType& GetHandle() const noexcept;

void Unsubscribe() noexcept;

protected:
using ProxyEvents = std::map<std::string_view, std::reference_wrapper<ProxyEventBase>>;
using ProxyFields = std::map<std::string_view, std::reference_wrapper<ProxyFieldBase>>;
Expand Down
2 changes: 2 additions & 0 deletions score/mw/com/impl/proxy_binding.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class ProxyBinding
virtual void UnregisterEventBinding(const std::string_view service_element_name) noexcept = 0;

virtual Result<void> SetupMethods() = 0;

virtual void ShutdownBinding() noexcept = 0;
};

} // namespace score::mw::com::impl
Expand Down
2 changes: 2 additions & 0 deletions score/mw/com/impl/proxy_event_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ ProxyEventBase::~ProxyEventBase() noexcept
<< "Proxy event instance destroyed while still holding SamplePtr instances, terminating.";
std::terminate();
}

this->Unsubscribe();
}

ProxyEventBase::ProxyEventBase(ProxyEventBase&&) noexcept = default;
Expand Down
38 changes: 38 additions & 0 deletions score/mw/com/impl/traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,38 @@ class ProxyWrapperClass : public Interface<Trait>
return proxy_wrapper;
}

~ProxyWrapperClass()
{
if (is_proxy_owner_.IsSet())
{
this->Unsubscribe();
}
}

ProxyWrapperClass(const ProxyWrapperClass&) = delete;
ProxyWrapperClass& operator=(const ProxyWrapperClass&) = delete;

ProxyWrapperClass(ProxyWrapperClass&& other) noexcept
: Interface<Trait>{std::move(static_cast<Interface<Trait>&&>(other))},
is_proxy_owner_{std::move(other.is_proxy_owner_)}
{
}

ProxyWrapperClass& operator=(ProxyWrapperClass&& other) noexcept
{
if (&other != this)
{
if (is_proxy_owner_.IsSet())
{
this->Unsubscribe();
}

Interface<Trait>::operator=(std::move(static_cast<Interface<Trait>&&>(other)));
is_proxy_owner_ = std::move(other.is_proxy_owner_);
}
return *this;
}

private:
/// \brief Constructs ProxyWrapperClass
explicit ProxyWrapperClass(HandleType instance_handle, std::unique_ptr<ProxyBinding> proxy_binding)
Expand All @@ -379,6 +411,12 @@ class ProxyWrapperClass : public Interface<Trait>
}

static std::optional<std::unordered_map<HandleType, std::queue<Result<ProxyWrapperClass>>>> creation_results_;

/// \brief Flag which is checked before calling Unsubscribe in the destructor of this class
///
/// This flag is always set for a Proxy except when a Proxy is moved. In this case, this flag will be cleared
/// in the moved-from class so that that object doesn't call Unsubscribe on destruction.
FlagOwner is_proxy_owner_{true};
};
template <template <class> class Interface, class Trait>
std::optional<std::unordered_map<HandleType, std::queue<Result<ProxyWrapperClass<Interface, Trait>>>>>
Expand Down
Loading