aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp
diff options
context:
space:
mode:
authorVasily Gerasimov <UgnineSirdis@gmail.com>2022-02-18 15:51:50 +0300
committerVasily Gerasimov <UgnineSirdis@gmail.com>2022-02-18 15:51:50 +0300
commit8d57865afed51c644443d0ecf764a573c708cc00 (patch)
tree99fb97433bad7476712263772102dafcb26e0b53 /library/cpp
parenteb15faa9ae95ee81f45268f14fcee30f4494da92 (diff)
downloadydb-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.h31
-rw-r--r--library/cpp/actors/core/actor_ut.cpp79
-rw-r--r--library/cpp/actors/core/hfunc.h20
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); \
+ }