diff --git a/rd-cpp/src/rd_core_cpp/src/main/CMakeLists.txt b/rd-cpp/src/rd_core_cpp/src/main/CMakeLists.txt index db04f7fc9..6c27f4ad8 100644 --- a/rd-cpp/src/rd_core_cpp/src/main/CMakeLists.txt +++ b/rd-cpp/src/rd_core_cpp/src/main/CMakeLists.txt @@ -37,6 +37,7 @@ set(RD_CORE_CPP_SOURCES #pch ${PCH_CPP_OPT} util/export_api_helper.h + util/lifetime_util.h ) if (RD_STATIC) diff --git a/rd-cpp/src/rd_core_cpp/src/main/util/lifetime_util.h b/rd-cpp/src/rd_core_cpp/src/main/util/lifetime_util.h new file mode 100644 index 000000000..5984b6639 --- /dev/null +++ b/rd-cpp/src/rd_core_cpp/src/main/util/lifetime_util.h @@ -0,0 +1,37 @@ +#ifndef LIFETIME_UTIL_H +#define LIFETIME_UTIL_H + +#include +#include "../lifetime/LifetimeDefinition.h" + +namespace rd +{ +namespace util +{ +/// \brief Attaches lifetime to shared_ptr. Lifetime terminates when shared_ptr destructed. +/// \param original original pointer which will be used to make a new pointer with lifetime. +/// \param lifetime_definition Lifetime definition associated with returned shared_ptr. +/// \return New shared_ptr which owns lifetime_definition and terminates that lifetime when destroyed. +template +static std::shared_ptr attach_lifetime(std::shared_ptr original, LifetimeDefinition lifetime_definition) +{ + struct Deleter + { + std::shared_ptr ptr; + LifetimeDefinition lifetime_definition; + + explicit Deleter(LifetimeDefinition&& lifetime_definition, std::shared_ptr ptr) : ptr(std::move(ptr)), lifetime_definition(std::move(lifetime_definition)) { } + + void operator()(T*) const + { + } + }; + + auto raw_ptr = original.get(); + auto deleter = Deleter(std::move(lifetime_definition), std::move(original)); + return std::shared_ptr(raw_ptr, std::move(deleter)); +} +} +} + +#endif //LIFETIME_UTIL_H diff --git a/rd-cpp/src/rd_framework_cpp/src/main/task/RdEndpoint.h b/rd-cpp/src/rd_framework_cpp/src/main/task/RdEndpoint.h index 6c6e322bb..3e74f9773 100644 --- a/rd-cpp/src/rd_framework_cpp/src/main/task/RdEndpoint.h +++ b/rd-cpp/src/rd_framework_cpp/src/main/task/RdEndpoint.h @@ -119,9 +119,9 @@ class RdEndpoint : public virtual RdReactiveBase, public ISerializable template , bool> = true> void handle_result(LifetimeDefinition result_lifetime_def, const RdId task_id, const TaskResult& result) const { - try + if (result.is_succeeded()) { - if (result.is_succeeded()) + try { auto result_lifetime = result_lifetime_def.lifetime; auto wired_result = result_lifetime->make_attached>(std::move(result_lifetime_def), result.get_value()); @@ -129,31 +129,30 @@ class RdEndpoint : public virtual RdReactiveBase, public ISerializable wired_result->bind(result_lifetime, this, "EndpointWiredResult"); send_result(task_id, result); } - else + catch (const std::exception& ex) { - send_result(task_id, result); - result_lifetime_def.terminate(); + spdlog::get("logSend")->error(ex.what()); + send_result(task_id, typename TaskResult::Fault(ex)); } } - catch (std::exception ex) + else { - spdlog::get("logSend")->error(ex.what()); - result_lifetime_def.terminate(); + send_result(task_id, result); } } template , bool> = true> - void handle_result(LifetimeDefinition result_lifetime_def, const RdId task_id, TaskResult result) const + void handle_result(LifetimeDefinition /*should_be_destroyed_on_complete*/, const RdId task_id, TaskResult result) const { try { send_result(task_id, result); - result_lifetime_def.terminate(); } - catch (std::exception ex) + catch (const std::exception& ex) { spdlog::get("logSend")->error(ex.what()); - result_lifetime_def.terminate(); + if (result.is_succeeded()) + send_result(task_id, typename TaskResult::Fault(ex)); } } diff --git a/rd-cpp/src/rd_framework_cpp/src/main/task/RdTaskResult.h b/rd-cpp/src/rd_framework_cpp/src/main/task/RdTaskResult.h index 042f18477..50b431d5a 100644 --- a/rd-cpp/src/rd_framework_cpp/src/main/task/RdTaskResult.h +++ b/rd-cpp/src/rd_framework_cpp/src/main/task/RdTaskResult.h @@ -119,33 +119,6 @@ class RdTaskResult final : public ISerializable v); } - /// \brief Attaches lifetime to result value. Lifetime terminates when result value destructed. - /// \param parent Parent lifetime. - /// \throw mpark::bad_variant_access if result isn't available or not Success - template , bool> = true> - Lifetime attach_nested_lifetime_to_value(const Lifetime& parent) - { - auto&& wrapper = get(v).value; - - struct Deleter - { - std::shared_ptr ptr; - LifetimeDefinition lifetime_definition; - - explicit Deleter(LifetimeDefinition&& lifetime_definition, std::shared_ptr ptr) : ptr(std::move(ptr)), lifetime_definition(std::move(lifetime_definition)) { } - - void operator()(T*) const - { - } - }; - - auto deleter = Deleter(LifetimeDefinition(parent), std::move(wrapper)); - auto ptr = deleter.ptr.get(); - auto lifetime = deleter.lifetime_definition.lifetime; - wrapper = std::shared_ptr(ptr, std::move(deleter)); - return lifetime; - } - WT const& get_value() const { return visit(util::make_visitor([](Success const& value) -> WT const& { return value.value; }, diff --git a/rd-cpp/src/rd_framework_cpp/src/main/task/WiredRdTaskImpl.h b/rd-cpp/src/rd_framework_cpp/src/main/task/WiredRdTaskImpl.h index 0fd12b313..259b25d58 100644 --- a/rd-cpp/src/rd_framework_cpp/src/main/task/WiredRdTaskImpl.h +++ b/rd-cpp/src/rd_framework_cpp/src/main/task/WiredRdTaskImpl.h @@ -4,6 +4,7 @@ #include "serialization/Polymorphic.h" #include "RdTaskResult.h" #include "util/framework_traits.h" +#include "util/lifetime_util.h" namespace rd { @@ -26,9 +27,14 @@ class WiredRdTaskImpl : public RdReactiveBase LifetimeImpl::counter_t termination_lifetime_id{}; template , bool> = true> - void bind_result(TaskResult& task_result) const + TaskResult bind_result(TaskResult task_result) const { - auto result_lifetime = task_result.attach_nested_lifetime_to_value(lifetime); + if (!task_result.is_succeeded()) + return task_result; + + auto lifetime_defintion = LifetimeDefinition(lifetime); + auto result_lifetime = lifetime_defintion.lifetime; + auto value = util::attach_lifetime(task_result.get_value(), std::move(lifetime_defintion)); result_lifetime->add_action([task_id = get_id(), cutpoint = cutpoint] { cutpoint->get_wire()->send(task_id, [](auto&) @@ -36,13 +42,14 @@ class WiredRdTaskImpl : public RdReactiveBase // write nothing, just signal server to release result lifetime }); }); - task_result.get_value()->bind(result_lifetime, cutpoint, "CallResult"); + value->bind(result_lifetime, cutpoint, "CallResult"); + return typename TaskResult::Success(value); } template , bool> = true> - void bind_result(TaskResult&) const + TaskResult bind_result(TaskResult result) const { - // do nothing for non-bindable value + return result; } public: @@ -78,7 +85,7 @@ class WiredRdTaskImpl : public RdReactiveBase } else { - bind_result(result); + result = bind_result(std::move(result)); this->result->set_if_empty(std::move(result)); } });