Skip to content
Draft
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ class "score::mw::com::impl::SkeletonEventBase" {
+SkeletonEventBase(std::unique_ptr<SkeletonEventBindingBase> binding)
+PrepareOffer(): score::Result<void>
+PrepareStopOffer(): void
+UpdateSkeletonReference(SkeletonBase& base_skeleton): void
-binding_: std::unique_ptr<SkeletonEventBindingBase>
-tracing_data_: SkeletonEventTracing
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ abstract class "score::mw::com::impl::SkeletonBase" as SkeletonBase {
+StopOfferService(): void
--
Notes:
SkeletonBase is moveable but not copyable. On moving, the SkeletonBase should call
UpdateSkeletonReference on all events and fields within its events_ and fields_ maps.
SkeletonBase is moveable but not copyable. On moving, the SkeletonBase updates method references.
}

class SkeletonBinding {
Expand Down Expand Up @@ -91,7 +90,6 @@ abstract class "score::mw::com::impl::SkeletonFieldBase" as SkeletonFieldBase {
+SkeletonFieldBase(SkeletonBase&, std::string_view field_name, std::unique_ptr<impl::SkeletonEventBase>)
+PrepareOffer(): Result<void>
+PrepareStopOffer(): void
+UpdateSkeletonReference(SkeletonBase& base_skeleton): void

-IsInitialValueSaved(): bool = 0
-DoDeferredUpdate(): Result<void> = 0
Expand All @@ -108,7 +106,6 @@ class "score::mw::com::impl::SkeletonEventBase" as SkeletonEventBase {
+SkeletonEventBase(std::unique_ptr<SkeletonEventBindingBase> binding)
+PrepareOffer(): score::Result<void>
+PrepareStopOffer(): void
+UpdateSkeletonReference(SkeletonBase& base_skeleton): void

--
Notes:
Expand All @@ -118,8 +115,7 @@ class "score::mw::com::impl::SkeletonEventBase" as SkeletonEventBase {
This allows SkeletonEventBase to access the type independent methods of
SkeletonEventBindingBase. Derived classes i.e. impl::SkeletonEvent should
downcast binding_ to a SkeletonEventBinding<SampleType> in order to use type
dependent methods. On moving, the SkeletonEvent should call UpdateEvent on its
parent skeleton so that the parent stores its new address.
dependent methods.
}

class SkeletonServiceMethodBinding <InArgs, OutArgs> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ abstract class "score::mw::com::impl::SkeletonBase" as ScoreMwComImplSkeletonBas
+StopOfferService(): void
--
Notes:
SkeletonBase is moveable but not copyable. On moving, the SkeletonBase should call UpdateSkeletonReference on all
events and fields within its events_ and fields_ maps.
SkeletonBase is moveable but not copyable. On moving, the SkeletonBase updates method references.
}

abstract class "DummySkeleton\n{{generated}}" as DummySkeleton {
Expand All @@ -75,7 +74,6 @@ class "score::mw::com::impl::SkeletonEventBase" as ScoreMwComImplSkeletonEventBa
+SkeletonEventBase(std::unique_ptr<SkeletonEventBindingBase> binding)
+PrepareOffer(): score::Result<void>
+PrepareStopOffer(): void
+UpdateSkeletonReference(SkeletonBase& base_skeleton): void
--
Notes:
SkeletonEventBase is moveable but not copyable.
Expand All @@ -84,15 +82,13 @@ class "score::mw::com::impl::SkeletonEventBase" as ScoreMwComImplSkeletonEventBa
This allows SkeletonEventBase to access the type independent methods of
SkeletonEventBindingBase. Derived classes i.e. impl::SkeletonEvent should
downcast binding_ to a SkeletonEventBinding<SampleType> in order to use type
dependent methods. On moving, the SkeletonEvent should call UpdateEvent on its
parent skeleton so that the parent stores its new address.
dependent methods.
}

class "score::mw::com::impl::SkeletonFieldBase" as ScoreMwComImplSkeletonFieldBase {
+SkeletonFieldBase(SkeletonBase&, std::string_view field_name, std::unique_ptr<impl::SkeletonEventBase>)
+PrepareOffer(): Result<void>
+PrepareStopOffer(): void
+UpdateSkeletonReference(SkeletonBase& base_skeleton): void
--
#skeleton_event_dispatch_ : std::unique_ptr<impl::SkeletonEventBase>
#skeleton_base_ : std::reference_wrapper<SkeletonBase>
Expand Down
28 changes: 28 additions & 0 deletions score/mw/com/impl/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ cc_library(
deps = [
":data_type_meta_info",
":generic_skeleton_event_binding",
":reference_to_moveable",
":skeleton_base",
":skeleton_event_base",
":skeleton_event_binding",
Expand Down Expand Up @@ -243,6 +244,7 @@ cc_library(
],
deps = [
":instance_identifier",
":reference_to_moveable",
":runtime",
":skeleton_base",
":skeleton_event_base",
Expand Down Expand Up @@ -355,6 +357,7 @@ cc_library(
],
deps = [
":flag_owner",
":reference_to_moveable",
":skeleton_event_binding",
"//score/mw/com/impl/tracing:skeleton_event_tracing",
"//score/mw/com/impl/tracing:skeleton_event_tracing_data",
Expand All @@ -374,6 +377,7 @@ cc_library(
],
deps = [
":error",
":reference_to_moveable",
":skeleton_event_base",
"//score/mw/com/impl/methods:skeleton_method_base",
"@score_baselibs//score/language/futurecpp",
Expand All @@ -396,6 +400,7 @@ cc_library(
deps = [
":flag_owner",
":instance_identifier",
":reference_to_moveable",
":runtime",
":skeleton_binding",
":skeleton_event_base",
Expand Down Expand Up @@ -1064,6 +1069,18 @@ cc_library(
],
)

cc_library(
name = "reference_to_moveable",
srcs = [
"reference_to_moveable.cpp",
],
hdrs = [
"reference_to_moveable.h",
],
features = COMPILER_WARNING_FEATURES,
tags = ["FFI"],
)

cc_unit_test(
name = "unit_test_runtime_single_exec",
srcs = ["runtime_single_exec_test.cpp"],
Expand Down Expand Up @@ -1329,6 +1346,17 @@ cc_unit_test(
],
)

cc_unit_test(
name = "reference_to_moveable_test",
srcs = [
"reference_to_moveable_test.cpp",
],
features = COMPILER_WARNING_FEATURES,
deps = [
":reference_to_moveable",
],
)

cc_unit_test(
name = "unit_test",
srcs = [
Expand Down
2 changes: 1 addition & 1 deletion score/mw/com/impl/generic_skeleton_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ GenericSkeletonEvent::GenericSkeletonEvent(SkeletonBase& skeleton_base,
std::unique_ptr<GenericSkeletonEventBinding> binding)
: SkeletonEventBase(skeleton_base, event_name, std::move(binding))
{
SkeletonBaseView{skeleton_base}.RegisterEvent(event_name, *this);
SkeletonBaseView{skeleton_base}.RegisterEvent(event_name, reference_to_moveable_.Get());

if (binding_ != nullptr)
{
Expand Down
57 changes: 57 additions & 0 deletions score/mw/com/impl/methods/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,46 @@ cc_library(
],
)

cc_library(
name = "method_traits_checker",
srcs = ["method_traits_checker.cpp"],
hdrs = ["method_traits_checker.h"],
features = COMPILER_WARNING_FEATURES,
tags = ["FFI"],
visibility = [
"//score/mw/com:__subpackages__",
],
deps = [
":callable_traits",
"@score_baselibs//score/language/futurecpp",
],
)

cc_library(
name = "callable_traits",
hdrs = [
"callable_traits.h",
"callable_traits_impl.h",
],
features = COMPILER_WARNING_FEATURES,
tags = ["FFI"],
visibility = [
"//score/mw/com:__subpackages__",
],
deps = [
],
)

cc_unit_test(
name = "callable_traits_test",
srcs = ["callable_traits_test.cpp"],
deps = [
":callable_traits",
"//score/mw/com/impl/methods/test:callable_traits_resources",
"@googletest//:gtest",
],
)

cc_library(
name = "proxy_method_base",
srcs = ["proxy_method_base.cpp"],
Expand Down Expand Up @@ -111,6 +151,20 @@ cc_unit_test(
],
)

cc_unit_test(
name = "method_traits_checker_test",
srcs = ["method_traits_checker_test.cpp"],
features = COMPILER_WARNING_FEATURES + [
# These tests catch exceptions instead of using gtest EXPECT_DEATH so we disable aborts_upon_exception.
"-aborts_upon_exception",
],
deps = [
":method_traits_checker",
"@googletest//:gtest",
"@score_baselibs//score/language/futurecpp:futurecpp_test_support",
],
)

cc_unit_test(
name = "proxy_method_test",
srcs = ["proxy_method_test.cpp"],
Expand Down Expand Up @@ -140,6 +194,7 @@ cc_library(
deps = [
":skeleton_method_binding",
"//score/mw/com/impl:method_type",
"//score/mw/com/impl:reference_to_moveable",
"//score/mw/com/impl/util:type_erased_storage",
],
)
Expand All @@ -154,6 +209,7 @@ cc_library(
"//score/mw/com/impl:__subpackages__",
],
deps = [
":method_traits_checker",
":skeleton_method_binding",
"//score/mw/com/impl:instance_identifier",
"//score/mw/com/impl:skeleton_base",
Expand Down Expand Up @@ -186,6 +242,7 @@ cc_unit_test(
deps = [
":skeleton_method",
"//score/mw/com/impl/bindings/mock_binding",
"//score/mw/com/impl/methods/test:callable_traits_resources",
"//score/mw/com/impl/plumbing:skeleton_method_binding_factory_mock",
"//score/mw/com/impl/test:binding_factory_resources",
"@score_baselibs//score/language/futurecpp",
Expand Down
13 changes: 13 additions & 0 deletions score/mw/com/impl/methods/callable_traits.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/********************************************************************************
* Copyright (c) 2025 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/
#include "score/mw/com/impl/methods/method_handler_traits.h"
79 changes: 79 additions & 0 deletions score/mw/com/impl/methods/callable_traits.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/********************************************************************************
* Copyright (c) 2025 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/
#ifndef SCORE_MW_COM_IMPL_METHODS_METHOD_CALLABLE_TRAITS_H
#define SCORE_MW_COM_IMPL_METHODS_METHOD_CALLABLE_TRAITS_H

#include <tuple>
#include <type_traits>

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

/// \brief Implementation of std::remove_cvref which is only available in C++20.
template <typename T>
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;

/// \brief Helper struct to check if a tuple type is empty.
template <typename T, typename = void>
struct is_tuple_empty : std::false_type
{
};

template <typename T>
struct is_tuple_empty<T, std::enable_if_t<std::tuple_size_v<T> == 0U>> : std::true_type
{
};

template <typename T>
using is_tuple_empty_t = typename is_tuple_empty<T>::type;

/// \brief Helper struct to extract the tail of a tuple (i.e. all elements except the first one) as a tuple type.
template <typename... T>
struct get_tuple_tail;

template <typename Head, typename... Tail>
struct get_tuple_tail<std::tuple<Head, Tail...>>
{
using type = std::tuple<Tail...>;
};

template <typename T>
using get_tuple_tail_t = typename get_tuple_tail<T>::type;

/// \brief Helper struct to extract the in argument types of a callable as a tuple type in member alias `type`.
///
/// e.g. for a callable of type `int(const double&, int, const std::string), `get_callable_args_types<int(const
/// double&, int, const std::string)>::type` will be `std::tuple<const double&, int, const std::string>`.
/// Full implementation is in callable_traits_impl.h.
template <typename T>
struct get_callable_args_types : public get_callable_args_types<decltype(&remove_cvref_t<T>::operator())>
{
};

/// \brief Helper struct to extract the return type of a callable as a type in member alias `type`.
///
/// e.g. for a callable of type `int(const double&, int, const std::string), `get_callable_return_type<int(const
/// double&, int, const std::string)>::type` will be `int`.
/// Full implementation is in callable_traits_impl.h.
template <typename T>
struct get_callable_return_type : public get_callable_return_type<decltype(&remove_cvref_t<T>::operator())>
{
};

} // namespace score::mw::com::impl

// To avoid keeping the large number of struct specializations for different callable types in the header file, we put
// them in a separate implementation header file.
#include "score/mw/com/impl/methods/callable_traits_impl.h"

#endif // SCORE_MW_COM_IMPL_METHODS_METHOD_CALLABLE_TRAITS_H
Loading
Loading