diff --git a/score/mw/com/impl/bindings/lola/proxy.cpp b/score/mw/com/impl/bindings/lola/proxy.cpp index 89e3d1d16..2f28d87bb 100644 --- a/score/mw/com/impl/bindings/lola/proxy.cpp +++ b/score/mw/com/impl/bindings/lola/proxy.cpp @@ -600,7 +600,7 @@ bool Proxy::IsEventProvided(const std::string_view event_name) const noexcept return event_exists; } -score::Result Proxy::SetupMethods() +score::Result Proxy::SetupMethods(const std::size_t additional_shm_size_bytes) { auto enabled_method_data = GetMethodIdAndQueueSizeForEnabledMethods(); @@ -672,7 +672,7 @@ score::Result Proxy::SetupMethods() } const auto type_erased_element_infos = GetTypeErasedElementInfoForEnabledMethods(enabled_method_data); - const auto required_shm_size = CalculateRequiredShmSize(type_erased_element_infos); + const auto required_shm_size = CalculateRequiredShmSize(type_erased_element_infos) + additional_shm_size_bytes; const auto skeleton_shm_permissions = GetSkeletonShmPermissions(); method_shm_resource_ = memory::shared::SharedMemoryFactory::Create( diff --git a/score/mw/com/impl/bindings/lola/proxy.h b/score/mw/com/impl/bindings/lola/proxy.h index 99fa9f653..b4fbe8307 100644 --- a/score/mw/com/impl/bindings/lola/proxy.h +++ b/score/mw/com/impl/bindings/lola/proxy.h @@ -167,7 +167,16 @@ class Proxy : public ProxyBinding /// \return True if the event name exists, otherwise, false bool IsEventProvided(const std::string_view event_name) const noexcept override; - score::Result SetupMethods() override; + /// \brief Sets up the shared memory for all the methods of the proxy, notifies the skeleton to open the shared + /// memory and perform any setup on skeleton side. + /// + /// After creating the shared memory, the proxy sends a blocking message which waits for a reply via message passing + /// to the skeleton. The skeleton will then open the shared memory and perform any setup on its side. The proxy will + /// then wait for an acknowledgement from the skeleton that it has completed its setup. + /// + /// \return result which contains an error if setup on the proxy or skeleton side failed or if the message passing + /// communication with the skeleton failed. + score::Result SetupMethods(const std::size_t additional_shm_size_bytes = 0) override; QualityType GetQualityType() const noexcept; @@ -192,6 +201,14 @@ class Proxy : public ProxyBinding /// \note Idempotent: calling it more than once is safe. void FinalizeDeinitialize() override; + memory::shared::ManagedMemoryResource& GetMethodMemoryResource() noexcept + { + SCORE_LANGUAGE_FUTURECPP_PRECONDITION_PRD_MESSAGE( + method_shm_resource_ != nullptr, + "Proxy::GetControlMemoryResource: Methods managed memory resource pointer is null"); + return *method_shm_resource_; + } + private: static std::atomic current_proxy_instance_counter_; diff --git a/score/mw/com/impl/bindings/mock_binding/proxy.h b/score/mw/com/impl/bindings/mock_binding/proxy.h index a3e270c99..7092c4cff 100644 --- a/score/mw/com/impl/bindings/mock_binding/proxy.h +++ b/score/mw/com/impl/bindings/mock_binding/proxy.h @@ -17,6 +17,7 @@ #include "score/result/result.h" #include +#include namespace score::mw::com::impl::mock_binding { @@ -29,7 +30,7 @@ class Proxy : public ProxyBinding ~Proxy() override = default; MOCK_METHOD(bool, IsEventProvided, (const std::string_view), (const, noexcept, override)); - MOCK_METHOD(Result, SetupMethods, (), (override)); + MOCK_METHOD(Result, SetupMethods, (std::size_t), (override)); MOCK_METHOD(void, PrepareDeinitialize, (), (override)); MOCK_METHOD(void, FinalizeDeinitialize, (), (override)); }; @@ -45,9 +46,9 @@ class ProxyFacade : public ProxyBinding return proxy_.IsEventProvided(event_name); } - Result SetupMethods() override + Result SetupMethods(std::size_t additional_shm_size_bytes) override { - return proxy_.SetupMethods(); + return proxy_.SetupMethods(additional_shm_size_bytes); } void PrepareDeinitialize() override diff --git a/score/mw/com/impl/methods/proxy_method.h b/score/mw/com/impl/methods/proxy_method.h index 2e75fdc20..71b45a289 100644 --- a/score/mw/com/impl/methods/proxy_method.h +++ b/score/mw/com/impl/methods/proxy_method.h @@ -13,9 +13,11 @@ #ifndef SCORE_MW_COM_IMPL_METHODS_PROXY_METHOD_H #define SCORE_MW_COM_IMPL_METHODS_PROXY_METHOD_H +#include "score/mw/com/impl/bindings/lola/proxy.h" #include "score/mw/com/impl/com_error.h" #include "score/mw/com/impl/methods/method_signature_element_ptr.h" #include "score/mw/com/impl/methods/proxy_method_binding.h" +#include "score/mw/com/impl/proxy_binding.h" #include "score/mw/com/impl/util/type_erased_storage.h" #include "score/containers/dynamic_array.h" @@ -146,12 +148,35 @@ score::Result...>> AllocateImpl( std::move(method_in_arg_ptr_tuple)); } +template +void InitializeArg(void* arg_pointer, ProxyBinding& proxy_binding) +{ + if constexpr (std::is_constructible_v&>) + { + // Temporary workaround to support using types which dynamically allocate memory at runtime (SWP-269486). These + // types must take a memory::shared::PolymorphicOffsetPtrAllocator as the only argument in their constructor. + // We need to propagate the shared memory resource from the lola binding to the constructor of the type so that + // the dynamic memory allocation can be done in shared memory. This is a temporary workaround and is not public. + auto* const lola_proxy_binding = dynamic_cast(&proxy_binding); + SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE(lola_proxy_binding != nullptr, + "ProxyBinding must be of type lola::Proxy, since ArgType is " + "constructible with a PolymorphicOffsetPtrAllocator"); + auto& methods_memory_resource = lola_proxy_binding->GetMethodMemoryResource(); + memory::shared::PolymorphicOffsetPtrAllocator allocator{methods_memory_resource}; + score::cpp::ignore = new (arg_pointer) T{allocator}; + } + else + { + score::cpp::ignore = new (arg_pointer) T{}; + } +} + /// \brief Initializes all InArgs by calling the default constructor for each argument. /// /// This step is important to avoid undefined behaviour (interpreting uninitialized memory) and also to ensure that any /// non-trivially constructible types are properly initialized. template -Result InitializeInArgs(ProxyMethodBinding& binding, const std::size_t queue_size) +Result InitializeInArgs(ProxyBinding& proxy_binding, ProxyMethodBinding& binding, const std::size_t queue_size) { for (std::size_t queue_index = 0U; queue_index < queue_size; ++queue_index) { @@ -165,8 +190,8 @@ Result InitializeInArgs(ProxyMethodBinding& binding, const std::size_t que // std::apply takes a callable and a tuple. It calls the callable with the arguments from the unpacked tuple. // E.g. In this case, it will call the lambda, fn, with: `fn(get<0>(args), get<1>(args), ..., get(args))` std::apply( - [](typename std::add_pointer::type... arg_pointers) { - ((score::cpp::ignore = new (arg_pointers) ArgTypes{}), ...); + [&proxy_binding](std::add_pointer_t... arg_pointers) { + (InitializeArg(arg_pointers, proxy_binding), ...); }, deserialized_arg_pointers); } @@ -178,7 +203,9 @@ Result InitializeInArgs(ProxyMethodBinding& binding, const std::size_t que /// This step is important to avoid undefined behaviour (interpreting uninitialized memory) and also to ensure that any /// non-trivially constructible types are properly initialized. template -Result InitializeReturnValue(ProxyMethodBinding& binding, const std::size_t queue_size) +Result InitializeReturnValue(ProxyBinding& proxy_binding, + ProxyMethodBinding& binding, + const std::size_t queue_size) { for (std::size_t queue_index = 0U; queue_index < queue_size; ++queue_index) { @@ -187,7 +214,7 @@ Result InitializeReturnValue(ProxyMethodBinding& binding, const std::size_ { return Unexpected(allocated_return_value_storage.error()); } - score::cpp::ignore = new (allocated_return_value_storage->data()) ReturnType{}; + InitializeArg(allocated_return_value_storage->data(), proxy_binding); } return {}; } diff --git a/score/mw/com/impl/methods/proxy_method_base.h b/score/mw/com/impl/methods/proxy_method_base.h index 48d45f538..aa7e78b0d 100644 --- a/score/mw/com/impl/methods/proxy_method_base.h +++ b/score/mw/com/impl/methods/proxy_method_base.h @@ -27,6 +27,8 @@ namespace score::mw::com::impl { +class ProxyBinding; + class ProxyMethodBase : public EnableReferenceToMoveableFromThis { public: @@ -58,7 +60,7 @@ class ProxyMethodBase : public EnableReferenceToMoveableFromThis InitializeInArgsAndReturnValues() = 0; + virtual Result InitializeInArgsAndReturnValues(ProxyBinding& proxy_binding) = 0; protected: /// \brief Size of the call-queue is currently fixed to 1! As soon as we are going to support larger call-queues, diff --git a/score/mw/com/impl/methods/proxy_method_test.cpp b/score/mw/com/impl/methods/proxy_method_test.cpp index 600e6184b..4bf976831 100644 --- a/score/mw/com/impl/methods/proxy_method_test.cpp +++ b/score/mw/com/impl/methods/proxy_method_test.cpp @@ -101,6 +101,11 @@ class ProxyMethodTestFixture : public ::testing::Test return &moved_method->second.get().Get(); } + ProxyBinding& GetProxyBinding() + { + return *ProxyBaseView{proxy_base_}.GetBinding(); + } + alignas(8) std::array method_in_args_buffer_{}; alignas(8) std::array method_return_type_buffer_{}; ConfigurationStore config_store_{InstanceSpecifier::Create(std::string{"/my_dummy_instance_specifier"}).value(), @@ -829,7 +834,7 @@ TEST_F(ProxyMethodWithNonTrivialConstructibleInArgsAndReturnFixture, InitializeI this->GivenAValidProxyMethod(); // When calling InitializeInArgsAndReturnValues - const auto result = this->unit_->InitializeInArgsAndReturnValues(); + const auto result = this->unit_->InitializeInArgsAndReturnValues(this->GetProxyBinding()); // Then a valid result is returned EXPECT_TRUE(result.has_value()); @@ -858,7 +863,7 @@ TEST_F(ProxyMethodWithNonTrivialConstructibleInArgsAndReturnFixture, .WillOnce(Return(MakeUnexpected(ComErrc::kBindingFailure))); // When calling InitializeInArgsAndReturnValues - const auto result = this->unit_->InitializeInArgsAndReturnValues(); + const auto result = this->unit_->InitializeInArgsAndReturnValues(this->GetProxyBinding()); // Then an error is returned ASSERT_FALSE(result.has_value()); @@ -875,7 +880,7 @@ TEST_F(ProxyMethodWithNonTrivialConstructibleInArgsAndReturnFixture, .WillOnce(Return(MakeUnexpected(ComErrc::kBindingFailure))); // When calling InitializeInArgsAndReturnValues - const auto result = this->unit_->InitializeInArgsAndReturnValues(); + const auto result = this->unit_->InitializeInArgsAndReturnValues(this->GetProxyBinding()); // Then an error is returned ASSERT_FALSE(result.has_value()); @@ -888,7 +893,7 @@ TEST_F(ProxyMethodWithNonTrivialConstructibleInArgsAndReturnFixture, this->GivenAValidProxyMethod(); // When calling InitializeInArgsAndReturnValues - this->unit_->InitializeInArgsAndReturnValues(); + this->unit_->InitializeInArgsAndReturnValues(this->GetProxyBinding()); // Then the zero copy call operator returns a pointer pointing to an initialized object (i.e. the non-trivial // default constructor was called, initializing value to NonTriviallyConstructibleType::kInitialValue @@ -910,7 +915,7 @@ TEST_F(ProxyMethodWithNonTrivialConstructibleInArgsAndReturnFixture, this->GivenAValidProxyMethod(); // When calling InitializeInArgsAndReturnValues - this->unit_->InitializeInArgsAndReturnValues(); + this->unit_->InitializeInArgsAndReturnValues(this->GetProxyBinding()); // Then the copy call operator returns a pointer pointing to an initialized object (i.e. the non-trivial // default constructor was called, initializing value to NonTriviallyConstructibleType::kInitialValue @@ -926,7 +931,7 @@ TEST_F(ProxyMethodWithNonTrivialConstructibleInArgsOnlyFixture, InitializeInArgs this->GivenAValidProxyMethod(); // When calling InitializeInArgsAndReturnValues - this->unit_->InitializeInArgsAndReturnValues(); + this->unit_->InitializeInArgsAndReturnValues(this->GetProxyBinding()); // Then Allocate returns a pointer pointing to an initialized object (i.e. the non-trivial default constructor was // called, initializing value to NonTriviallyConstructibleType::kInitialValue @@ -952,7 +957,7 @@ TEST_F(ProxyMethodWithNonTrivialConstructibleInArgsOnlyFixture, .WillOnce(Return(MakeUnexpected(ComErrc::kBindingFailure))); // When calling InitializeInArgsAndReturnValues - const auto result = this->unit_->InitializeInArgsAndReturnValues(); + const auto result = this->unit_->InitializeInArgsAndReturnValues(this->GetProxyBinding()); // Then an error is returned ASSERT_FALSE(result.has_value()); @@ -965,7 +970,7 @@ TEST_F(ProxyMethodWithNonTrivialConstructibleReturnOnlyFixture, this->GivenAValidProxyMethod(); // When calling InitializeInArgsAndReturnValues - this->unit_->InitializeInArgsAndReturnValues(); + this->unit_->InitializeInArgsAndReturnValues(this->GetProxyBinding()); // Then the copy call operator returns a pointer pointing to an initialized object (i.e. the non-trivial // default constructor was called, initializing value to NonTriviallyConstructibleType::kInitialValue @@ -986,7 +991,7 @@ TEST_F(ProxyMethodWithNonTrivialConstructibleReturnOnlyFixture, .WillOnce(Return(MakeUnexpected(ComErrc::kBindingFailure))); // When calling InitializeInArgsAndReturnValues - const auto result = this->unit_->InitializeInArgsAndReturnValues(); + const auto result = this->unit_->InitializeInArgsAndReturnValues(this->GetProxyBinding()); // Then an error is returned ASSERT_FALSE(result.has_value()); diff --git a/score/mw/com/impl/methods/proxy_method_with_in_args.h b/score/mw/com/impl/methods/proxy_method_with_in_args.h index cb7251a96..11c39adf4 100644 --- a/score/mw/com/impl/methods/proxy_method_with_in_args.h +++ b/score/mw/com/impl/methods/proxy_method_with_in_args.h @@ -85,7 +85,7 @@ class ProxyMethod final : public ProxyMethodBase ProxyMethod(ProxyMethod&&) noexcept = default; ProxyMethod& operator=(ProxyMethod&&) noexcept = default; - Result InitializeInArgsAndReturnValues() override; + Result InitializeInArgsAndReturnValues(ProxyBinding& proxy_binding) override; /// \brief Allocates the necessary storage for the argument values and the return value of a method call. /// \return On success, a tuple of MethodInArgPtr for each argument type is returned. On failure, an error code is @@ -158,10 +158,10 @@ score::Result ProxyMethod::operator()(MethodInArgPtr -Result ProxyMethod::InitializeInArgsAndReturnValues() +Result ProxyMethod::InitializeInArgsAndReturnValues(ProxyBinding& proxy_binding) { SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(binding_ != nullptr); - const auto init_in_args_result = detail::InitializeInArgs(*binding_, kCallQueueSize); + const auto init_in_args_result = detail::InitializeInArgs(proxy_binding, *binding_, kCallQueueSize); if (!init_in_args_result.has_value()) { return Unexpected(init_in_args_result.error()); diff --git a/score/mw/com/impl/methods/proxy_method_with_in_args_and_return.h b/score/mw/com/impl/methods/proxy_method_with_in_args_and_return.h index 90a42fc10..54669d8aa 100644 --- a/score/mw/com/impl/methods/proxy_method_with_in_args_and_return.h +++ b/score/mw/com/impl/methods/proxy_method_with_in_args_and_return.h @@ -20,6 +20,7 @@ #include "score/mw/com/impl/methods/proxy_method_binding.h" #include "score/mw/com/impl/plumbing/proxy_method_binding_factory.h" #include "score/mw/com/impl/proxy_base.h" +#include "score/mw/com/impl/proxy_binding.h" #include "score/mw/com/impl/util/type_erased_storage.h" #include "score/containers/dynamic_array.h" @@ -124,7 +125,7 @@ class ProxyMethod final : public ProxyMethodBase ProxyMethod(ProxyMethod&&) noexcept = default; ProxyMethod& operator=(ProxyMethod&&) noexcept = default; - Result InitializeInArgsAndReturnValues() override; + Result InitializeInArgsAndReturnValues(ProxyBinding& proxy_binding) override; /// \brief Allocates the necessary storage for the argument values and the return value of a method call. /// \return On success, a tuple of MethodInArgPtr for each argument type is returned. On failure, an error code is @@ -221,16 +222,16 @@ score::Result> ProxyMethod -Result ProxyMethod::InitializeInArgsAndReturnValues() +Result ProxyMethod::InitializeInArgsAndReturnValues(ProxyBinding& proxy_binding) { SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(binding_ != nullptr); - const auto init_in_args_result = detail::InitializeInArgs(*binding_, kCallQueueSize); + const auto init_in_args_result = detail::InitializeInArgs(proxy_binding, *binding_, kCallQueueSize); if (!init_in_args_result.has_value()) { return Unexpected(init_in_args_result.error()); } - const auto init_return_result = detail::InitializeReturnValue(*binding_, kCallQueueSize); + const auto init_return_result = detail::InitializeReturnValue(proxy_binding, *binding_, kCallQueueSize); if (!init_return_result.has_value()) { return Unexpected(init_return_result.error()); diff --git a/score/mw/com/impl/methods/proxy_method_with_return_type.h b/score/mw/com/impl/methods/proxy_method_with_return_type.h index 3c117d3dd..687f021e8 100644 --- a/score/mw/com/impl/methods/proxy_method_with_return_type.h +++ b/score/mw/com/impl/methods/proxy_method_with_return_type.h @@ -115,7 +115,7 @@ class ProxyMethod final : public ProxyMethodBase ProxyMethod(ProxyMethod&&) noexcept = default; ProxyMethod& operator=(ProxyMethod&&) noexcept = default; - Result InitializeInArgsAndReturnValues() override; + Result InitializeInArgsAndReturnValues(ProxyBinding& proxy_binding) override; /// \brief This is the call-operator of ProxyMethod with no arguments for a non-void ReturnType. score::Result> operator()(); @@ -172,10 +172,10 @@ score::Result> ProxyMethod::operat } template -Result ProxyMethod::InitializeInArgsAndReturnValues() +Result ProxyMethod::InitializeInArgsAndReturnValues(ProxyBinding& proxy_binding) { SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(binding_ != nullptr); - const auto init_return_result = detail::InitializeReturnValue(*binding_, kCallQueueSize); + const auto init_return_result = detail::InitializeReturnValue(proxy_binding, *binding_, kCallQueueSize); if (!init_return_result.has_value()) { return Unexpected(init_return_result.error()); diff --git a/score/mw/com/impl/methods/proxy_method_without_in_args_or_return.h b/score/mw/com/impl/methods/proxy_method_without_in_args_or_return.h index 0af7eb634..605ab1866 100644 --- a/score/mw/com/impl/methods/proxy_method_without_in_args_or_return.h +++ b/score/mw/com/impl/methods/proxy_method_without_in_args_or_return.h @@ -85,7 +85,7 @@ class ProxyMethod final : public ProxyMethodBase ProxyMethod(ProxyMethod&&) noexcept = default; ProxyMethod& operator=(ProxyMethod&&) noexcept = default; - Result InitializeInArgsAndReturnValues() override + Result InitializeInArgsAndReturnValues(ProxyBinding&) override { return {}; } diff --git a/score/mw/com/impl/proxy_base.cpp b/score/mw/com/impl/proxy_base.cpp index a5e6ddf49..9dc797766 100644 --- a/score/mw/com/impl/proxy_base.cpp +++ b/score/mw/com/impl/proxy_base.cpp @@ -101,9 +101,9 @@ score::Result ProxyBase::StopFindService(const FindServiceHandle handle) n return stop_find_service_result; } -Result ProxyBase::SetupMethods() +Result ProxyBase::SetupMethods(const std::size_t additional_shm_size_bytes) { - const auto result = proxy_binding_->SetupMethods(); + const auto result = proxy_binding_->SetupMethods(additional_shm_size_bytes); if (!result.has_value()) { return MakeUnexpected(result.error()); @@ -112,7 +112,7 @@ Result ProxyBase::SetupMethods() for (auto& method_key_value_pair : methods_) { auto& method = method_key_value_pair.second.get().Get(); - const auto method_init_result = method.InitializeInArgsAndReturnValues(); + const auto method_init_result = method.InitializeInArgsAndReturnValues(*proxy_binding_); if (!method_init_result.has_value()) { return MakeUnexpected(method_init_result.error()); diff --git a/score/mw/com/impl/proxy_base.h b/score/mw/com/impl/proxy_base.h index 09b4a7b64..ec39c1a71 100644 --- a/score/mw/com/impl/proxy_base.h +++ b/score/mw/com/impl/proxy_base.h @@ -146,7 +146,18 @@ class ProxyBase return is_proxy_binding_valid && are_service_element_bindings_valid_; } - Result SetupMethods(); + /// \brief Dispatches to the binding for any binding specific setup and then initializes all method InArgs and + /// Return values. + /// + /// The initialization of the InArgs and Return values is done on the binding independent level since the binding + /// level is type erased. The values are initialized once on startup and then reused (i.e. we never re-initialize + /// the values when calling a method). + /// + /// \param additional_shm_size_bytes Additional shared memory size in bytes to be allocated for methods in addition + /// to the size calculated for the size of the method in args and return values. This is a temporary workaround + /// added to allow using types which dynamically allocate memory once at runtime. This is not currently public and + /// should not be used by user applications. (SWP-269486) + Result SetupMethods(std::size_t additional_shm_size_bytes); // Suppress "AUTOSAR C++14 M11-0-1" rule findings. This rule states: "Member data in non-POD class types shall // be private.". We need these data elements to exchange this information between the ProxyBase and the diff --git a/score/mw/com/impl/proxy_base_test.cpp b/score/mw/com/impl/proxy_base_test.cpp index b939a956f..0563621d9 100644 --- a/score/mw/com/impl/proxy_base_test.cpp +++ b/score/mw/com/impl/proxy_base_test.cpp @@ -563,7 +563,7 @@ class DummyProxyMethod : public ProxyMethodBase { public: using ProxyMethodBase::ProxyMethodBase; - Result InitializeInArgsAndReturnValues() override + Result InitializeInArgsAndReturnValues(ProxyBinding&) override { return {}; } diff --git a/score/mw/com/impl/proxy_binding.h b/score/mw/com/impl/proxy_binding.h index d01f94e38..b66584673 100644 --- a/score/mw/com/impl/proxy_binding.h +++ b/score/mw/com/impl/proxy_binding.h @@ -17,6 +17,7 @@ #include "score/result/result.h" +#include #include #include @@ -54,7 +55,13 @@ class ProxyBinding /// \return True if the event name exists, otherwise, false virtual bool IsEventProvided(const std::string_view event_name) const noexcept = 0; - virtual Result SetupMethods() = 0; + /// \brief Performs any binding specific setup required. + /// + /// \param additional_shm_size_bytes Additional shared memory size in bytes to be allocated for methods in addition + /// to the size calculated for the size of the method in args and return values. This is a temporary workaround + /// added to allow using types which dynamically allocate memory once at runtime. This is not currently public and + /// should not be used by user applications. (SWP-269486) + virtual Result SetupMethods(std::size_t additional_shm_size_bytes) = 0; /// \brief Contains all cleanup logic for the binding that needs to be executed before any of the service elements /// are deinitialized (Called by ProxyBase::Deinitialize). diff --git a/score/mw/com/impl/proxy_binding_test.cpp b/score/mw/com/impl/proxy_binding_test.cpp index 21078abd8..582cdde41 100644 --- a/score/mw/com/impl/proxy_binding_test.cpp +++ b/score/mw/com/impl/proxy_binding_test.cpp @@ -14,6 +14,7 @@ #include +#include #include #include @@ -29,7 +30,7 @@ class MyProxy final : public ProxyBinding { return true; } - Result SetupMethods() override + Result SetupMethods(std::size_t) override { return {}; } diff --git a/score/mw/com/impl/traits.h b/score/mw/com/impl/traits.h index 4ce9f78da..39bc0ab7f 100644 --- a/score/mw/com/impl/traits.h +++ b/score/mw/com/impl/traits.h @@ -39,6 +39,7 @@ #include +#include #include #include #include @@ -87,6 +88,9 @@ class SkeletonWrapperClassTestView; template class ProxyWrapperClassTestView; +template +class ProxyWithSemiDynamicMethodFactory; + /// The main idea of these traits are to ease the interface creation for a user. It reduces the necessary generated code /// to a bare minimum. /// @@ -322,6 +326,8 @@ class ProxyWrapperClass : public Interface // coverity[autosar_cpp14_a11_3_1_violation] friend class ProxyWrapperClassTestView; + friend class ProxyWithSemiDynamicMethodFactory; + public: /// \api /// \brief Create a proxy instance from a service handle. @@ -331,31 +337,7 @@ class ProxyWrapperClass : public Interface /// \return On success, returns a ProxyWrapperClass instance. On failure, returns an error code. static Result Create(const HandleType instance_handle) noexcept { - if (creation_results_.has_value()) - { - return detail::ExtractCreationResultFrom(instance_handle, creation_results_.value()); - } - - auto proxy_binding = ProxyBindingFactory::Create(instance_handle); - - ProxyWrapperClass proxy_wrapper(instance_handle, std::move(proxy_binding)); - - if (!proxy_wrapper.AreBindingsValid()) - { - ::score::mw::log::LogError("lola") - << "Could not create ProxyWrapperClass as Proxy binding or service element " - "bindings could not be created."; - return MakeUnexpected(ComErrc::kBindingFailure); - } - - const auto setup_methods_result = proxy_wrapper.SetupMethods(); - if (!(setup_methods_result.has_value())) - { - ::score::mw::log::LogError("lola") << "Could not setup methods on Proxy side"; - return MakeUnexpected(ComErrc::kBindingFailure); - } - - return proxy_wrapper; + return Create(instance_handle, 0U); } ~ProxyWrapperClass() @@ -391,6 +373,40 @@ class ProxyWrapperClass : public Interface } private: + /// \brief Create a proxy instance from a service handle with additional shared memory size for methods. + /// + /// This is a temporary workaround added to allow using types which dynamically allocate memory once at runtime. + /// This is not currently public and should not be used by user applications. (SWP-269486). Can be accessed with + /// ProxyWithSemiDynamicMethodFactory::Create. + static Result Create(const HandleType instance_handle, + std::size_t additional_shm_size_bytes) noexcept + { + if (creation_results_.has_value()) + { + return detail::ExtractCreationResultFrom(instance_handle, creation_results_.value()); + } + + auto proxy_binding = ProxyBindingFactory::Create(instance_handle); + + ProxyWrapperClass proxy_wrapper(instance_handle, std::move(proxy_binding)); + + if (!proxy_wrapper.AreBindingsValid()) + { + ::score::mw::log::LogError("lola") + << "Could not create ProxyWrapperClass as Proxy binding or service element " + "bindings could not be created."; + return MakeUnexpected(ComErrc::kBindingFailure); + } + + const auto setup_methods_result = proxy_wrapper.SetupMethods(additional_shm_size_bytes); + if (!(setup_methods_result.has_value())) + { + ::score::mw::log::LogError("lola") << "Could not setup methods on Proxy side"; + return MakeUnexpected(ComErrc::kBindingFailure); + } + + return proxy_wrapper; + } /// \brief Constructs ProxyWrapperClass explicit ProxyWrapperClass(HandleType instance_handle, std::unique_ptr proxy_binding) : Interface{std::move(proxy_binding), std::move(instance_handle)}, is_proxy_owner_{true} @@ -432,6 +448,22 @@ using AsProxy = ProxyWrapperClass; template