diff options
author | Vasily Gerasimov <UgnineSirdis@gmail.com> | 2022-02-18 15:51:50 +0300 |
---|---|---|
committer | Vasily Gerasimov <UgnineSirdis@gmail.com> | 2022-02-18 15:51:50 +0300 |
commit | 8d57865afed51c644443d0ecf764a573c708cc00 (patch) | |
tree | 99fb97433bad7476712263772102dafcb26e0b53 /library/cpp | |
parent | eb15faa9ae95ee81f45268f14fcee30f4494da92 (diff) | |
download | ydb-8d57865afed51c644443d0ecf764a573c708cc00.tar.gz |
YQ-816 STRICT_STFUNC_EXC macro for handling events and exceptions
STRICT_STFUNC_EXC macro for handling events and exceptions
ref:7c4063586f79ab8f66018b2a0eac9d423134f82a
Diffstat (limited to 'library/cpp')
-rw-r--r-- | library/cpp/actors/core/actor.h | 31 | ||||
-rw-r--r-- | library/cpp/actors/core/actor_ut.cpp | 79 | ||||
-rw-r--r-- | library/cpp/actors/core/hfunc.h | 20 |
3 files changed, 122 insertions, 8 deletions
diff --git a/library/cpp/actors/core/actor.h b/library/cpp/actors/core/actor.h index ed29bd14b9..02cb48fec9 100644 --- a/library/cpp/actors/core/actor.h +++ b/library/cpp/actors/core/actor.h @@ -439,14 +439,29 @@ namespace NActors { #define STFUNC(funcName) void funcName(TAutoPtr< ::NActors::IEventHandle>& ev, const ::NActors::TActorContext& ctx) #define STATEFN(funcName) void funcName(TAutoPtr< ::NActors::IEventHandle>& ev, const ::NActors::TActorContext& ) -#define STRICT_STFUNC(NAME, HANDLERS) \ - void NAME(STFUNC_SIG) { \ - Y_UNUSED(ctx); \ - switch (const ui32 etype = ev->GetTypeRewrite()) { \ - HANDLERS \ - default: \ - Y_VERIFY_DEBUG(false, "%s: unexpected message type 0x%08" PRIx32, __func__, etype); \ - } \ +#define STFUNC_STRICT_UNHANDLED_MSG_HANDLER Y_VERIFY_DEBUG(false, "%s: unexpected message type 0x%08" PRIx32, __func__, etype); + +#define STFUNC_BODY(HANDLERS, UNHANDLED_MSG_HANDLER) \ + Y_UNUSED(ctx); \ + switch (const ui32 etype = ev->GetTypeRewrite()) { \ + HANDLERS \ + default: \ + UNHANDLED_MSG_HANDLER \ + } + +#define STRICT_STFUNC_BODY(HANDLERS) STFUNC_BODY(HANDLERS, STFUNC_STRICT_UNHANDLED_MSG_HANDLER) + +#define STRICT_STFUNC(NAME, HANDLERS) \ + void NAME(STFUNC_SIG) { \ + STRICT_STFUNC_BODY(HANDLERS) \ + } + +#define STRICT_STFUNC_EXC(NAME, HANDLERS, EXCEPTION_HANDLERS) \ + void NAME(STFUNC_SIG) { \ + try { \ + STRICT_STFUNC_BODY(HANDLERS) \ + } \ + EXCEPTION_HANDLERS \ } inline const TActorContext& TActivationContext::AsActorContext() { diff --git a/library/cpp/actors/core/actor_ut.cpp b/library/cpp/actors/core/actor_ut.cpp index e1b765ec72..6259c79919 100644 --- a/library/cpp/actors/core/actor_ut.cpp +++ b/library/cpp/actors/core/actor_ut.cpp @@ -5,6 +5,7 @@ #include "scheduler_basic.h" #include "actor_bootstrapped.h" +#include <library/cpp/actors/testlib/test_runtime.h> #include <library/cpp/actors/util/threadparkpad.h> #include <library/cpp/testing/unittest/registar.h> @@ -576,3 +577,81 @@ Y_UNIT_TEST_SUITE(TestDecorator) { UNIT_ASSERT((TEnumProcessKey<TActorActivityTag, IActor::EActorActivity>::GetIndex(IActor::INTERCONNECT_PROXY_TCP) == IActor::INTERCONNECT_PROXY_TCP)); } } + +Y_UNIT_TEST_SUITE(TestStateFunc) { + struct TTestActorWithExceptionsStateFunc : TActor<TTestActorWithExceptionsStateFunc> { + static constexpr char ActorName[] = "TestActorWithExceptionsStateFunc"; + + TTestActorWithExceptionsStateFunc() + : TActor<TTestActorWithExceptionsStateFunc>(&TTestActorWithExceptionsStateFunc::StateFunc) + { + } + + STRICT_STFUNC_EXC(StateFunc, + hFunc(TEvents::TEvWakeup, Handle), + ExceptionFunc(yexception, HandleException) + ExceptionFuncEv(std::exception, HandleException) + AnyExceptionFunc(HandleException) + ) + + void Handle(TEvents::TEvWakeup::TPtr& ev) { + Owner = ev->Sender; + switch (ev->Get()->Tag) { + case ETag::NoException: + SendResponse(ETag::NoException); + break; + case ETag::YException: + Cerr << "Throw yexception" << Endl; + throw yexception(); + case ETag::StdException: + Cerr << "Throw std::exception" << Endl; + throw std::runtime_error("trololo"); + case ETag::OtherException: + Cerr << "Throw trash" << Endl; + throw TString("1"); + default: + UNIT_ASSERT(false); + } + } + + void HandleException(const yexception&) { + Cerr << "Handle yexception" << Endl; + SendResponse(ETag::YException); + } + + void HandleException(const std::exception&, TAutoPtr<::NActors::IEventHandle>& ev) { + Cerr << "Handle std::exception from event with type " << ev->Type << Endl; + SendResponse(ETag::StdException); + } + + void HandleException() { + Cerr << "Handle trash" << Endl; + SendResponse(ETag::OtherException); + } + + enum ETag : ui64 { + NoException, + YException, + StdException, + OtherException, + }; + + void SendResponse(ETag tag) { + Send(Owner, new TEvents::TEvWakeup(tag)); + } + + TActorId Owner; + }; + + Y_UNIT_TEST(StateFuncWithExceptions) { + TTestActorRuntimeBase runtime; + runtime.Initialize(); + auto sender = runtime.AllocateEdgeActor(); + auto testActor = runtime.Register(new TTestActorWithExceptionsStateFunc()); + for (ui64 tag = 0; tag < 4; ++tag) { + runtime.Send(new IEventHandle(testActor, sender, new TEvents::TEvWakeup(tag)), 0, true); + auto ev = runtime.GrabEdgeEventRethrow<TEvents::TEvWakeup>(sender); + UNIT_ASSERT_VALUES_EQUAL(ev->Get()->Tag, tag); + } + } +} diff --git a/library/cpp/actors/core/hfunc.h b/library/cpp/actors/core/hfunc.h index 26f3c65013..a8e439e938 100644 --- a/library/cpp/actors/core/hfunc.h +++ b/library/cpp/actors/core/hfunc.h @@ -82,3 +82,23 @@ #define IgnoreFunc(TEvType) \ case TEvType::EventType: \ break; + +#define ExceptionFunc(ExceptionType, HandleFunc) \ + catch (const ExceptionType& exception) { \ + HandleFunc(exception); \ + } + +#define ExceptionFuncEv(ExceptionType, HandleFunc) \ + catch (const ExceptionType& exception) { \ + HandleFunc(exception, ev); \ + } + +#define AnyExceptionFunc(HandleFunc) \ + catch (...) { \ + HandleFunc(); \ + } + +#define AnyExceptionFuncEv(HandleFunc) \ + catch (...) { \ + HandleFunc(ev); \ + } |