aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/actors/core/event.h
diff options
context:
space:
mode:
authorxenoxeno <xeno@ydb.tech>2023-03-09 12:10:01 +0300
committerxenoxeno <xeno@ydb.tech>2023-03-09 12:10:01 +0300
commitad607bb887619f321dec03b02df8220e01b7f5aa (patch)
tree7d5c87352cbe835b56bb2bdac93b37cbdf8ead21 /library/cpp/actors/core/event.h
parent6324d075a5e80b6943b5de6b465b775050fe83df (diff)
downloadydb-ad607bb887619f321dec03b02df8220e01b7f5aa.tar.gz
light events for actor system
Diffstat (limited to 'library/cpp/actors/core/event.h')
-rw-r--r--library/cpp/actors/core/event.h628
1 files changed, 508 insertions, 120 deletions
diff --git a/library/cpp/actors/core/event.h b/library/cpp/actors/core/event.h
index 4eedeb0574..28e2c95e00 100644
--- a/library/cpp/actors/core/event.h
+++ b/library/cpp/actors/core/event.h
@@ -9,6 +9,7 @@
#include <util/system/hp_timer.h>
#include <util/generic/maybe.h>
+#include <util/string/builder.h>
namespace NActors {
class TChunkSerializer;
@@ -23,7 +24,7 @@ namespace NActors {
public ISerializerToStream {
protected:
// for compatibility with virtual actors
- virtual bool DoExecute(IActor* /*actor*/, std::unique_ptr<IEventHandle> /*eventPtr*/) {
+ virtual bool DoExecute(IActor* /*actor*/, std::unique_ptr<IEventHandleFat> /*eventPtr*/) {
Y_VERIFY_DEBUG(false);
return false;
}
@@ -33,7 +34,7 @@ namespace NActors {
virtual ~IEventBase() {
}
- bool Execute(IActor* actor, std::unique_ptr<IEventHandle> eventPtr) {
+ bool Execute(IActor* actor, std::unique_ptr<IEventHandleFat> eventPtr) {
return DoExecute(actor, std::move(eventPtr));
}
@@ -53,8 +54,70 @@ namespace NActors {
virtual TEventSerializationInfo CreateSerializationInfo() const { return {}; }
};
- // fat handle
- class IEventHandle : TNonCopyable {
+ struct IEventHandleFields {
+ enum EFlags : ui32 {
+ FlagTrackDelivery = 1 << 0,
+ FlagForwardOnNondelivery = 1 << 1,
+ FlagSubscribeOnSession = 1 << 2,
+ FlagUseSubChannel = 1 << 3,
+ FlagGenerateUnsureUndelivered = 1 << 4,
+ FlagExtendedFormat = 1 << 5,
+ FlagLight = 1 << 18,
+ FlagSerializable = 1 << 19,
+ };
+
+ static constexpr ui32 STICKY_FLAGS = (FlagLight | FlagSerializable);
+
+ TActorId Recipient = {};
+ TActorId Sender = {};
+ ui32 Type = {};
+
+#pragma pack(push, 1)
+ union {
+ ui32 Flags = {};
+ struct {
+ ui32 NormalFlags:6;
+ ui32 ReservedFlags:12;
+ ui32 StickyFlags:2;
+ ui32 Channel:12;
+ };
+ struct {
+ // flags
+ ui32 TrackDelivery:1;
+ ui32 ForwardOnNondeliveryFlag:1;
+ ui32 SubscribeOnSession:1;
+ ui32 UseSubChannel:1;
+ ui32 GenerateUnsureUndelivered:1;
+ ui32 ExtendedFormat:1;
+ // reserved
+ ui32 Reserved:12;
+ // sticky flags
+ ui32 Light:1;
+ ui32 Serializable:1;
+ };
+ };
+#pragma pack(pop)
+
+ ui64 Cookie = {};
+
+ TActorId RewriteRecipient = {};
+ ui32 RewriteType = {};
+
+ NWilson::TTraceId TraceId = {};
+
+#ifdef ACTORSLIB_COLLECT_EXEC_STATS
+ ::NHPTimer::STime SendTime = 0;
+#endif
+ };
+
+ class IEventHandle : public IEventHandleFields {
+ public:
+ IEventHandle(IEventHandleFields&& fields = {})
+ : IEventHandleFields(std::move(fields))
+ {}
+
+ virtual ~IEventHandle() = default;
+
struct TOnNondelivery {
TActorId Recipient;
@@ -64,28 +127,142 @@ namespace NActors {
}
};
+ THolder<TOnNondelivery> OnNondeliveryHolder; // only for local events
+
+ ui16 GetChannel() const noexcept {
+ return Channel;
+ }
+
+ ui64 GetSubChannel() const noexcept {
+ return UseSubChannel ? Sender.LocalId() : 0ULL;
+ }
+
+ // deprecate(xenoxeno) ?
+ static const size_t ChannelBits = 12;
+ static const size_t ChannelShift = (sizeof(ui32) << 3) - ChannelBits;
+
+ static ui32 MakeFlags(ui32 channel, ui32 flags) {
+ Y_VERIFY(channel < (1 << ChannelBits));
+ Y_VERIFY(flags < (1 << ChannelShift));
+ return (flags | (channel << ChannelShift));
+ }
+ //
+
+ void SetFlags(ui32 flags) {
+ Flags = (flags & ~STICKY_FLAGS) | (Flags & STICKY_FLAGS);
+ }
+
+ const TActorId& GetRecipientRewrite() const {
+ return RewriteRecipient;
+ }
+
+ void Rewrite(ui32 typeRewrite, TActorId recipientRewrite) {
+ RewriteRecipient = recipientRewrite;
+ RewriteType = typeRewrite;
+ }
+
+ void DropRewrite() {
+ RewriteRecipient = Recipient;
+ RewriteType = Type;
+ }
+
+ ui32 GetTypeRewrite() const {
+ return RewriteType;
+ }
+
+ bool IsEventLight() const {
+ return Light;
+ }
+
+ bool IsEventFat() const {
+ return !Light;
+ }
+
+ bool IsEventSerializable() const {
+ return Serializable;
+ }
+
+ template<typename TEventType>
+ TEventType* Get();
+ template<typename TEventType>
+ TEventType* CastAsLocal();
+ template<typename TEventType>
+ TEventType* StaticCastAsLocal();
+ bool HasEvent() const;
+ bool HasBuffer() const;
+ TString GetTypeName() const;
+ TString ToString() const;
+ size_t GetSize() const;
+ static TAutoPtr<IEventHandle>& Forward(TAutoPtr<IEventHandle>& ev, TActorId recipient);
+ static THolder<IEventHandle>& Forward(THolder<IEventHandle>& ev, TActorId recipient);
+ static TAutoPtr<IEventHandle> ForwardOnNondelivery(TAutoPtr<IEventHandle>& ev, ui32 reason, bool unsure = false);
+ static TAutoPtr<IEventHandle> ForwardOnNondelivery(std::unique_ptr<IEventHandle>& ev, ui32 reason, bool unsure = false);
+ template<typename TEventType>
+ static TEventType* Release(TAutoPtr<IEventHandle>&);
+ template<typename TEventType>
+ static TEventType* Release(THolder<IEventHandle>&);
+ template<typename TEventType>
+ static TEventType* Release(std::unique_ptr<IEventHandle>&);
+
+ template<typename TEventTypeSmartPtr>
+ static TAutoPtr<IEventHandle> ForwardOnNondelivery(TEventTypeSmartPtr& ev, ui32 reason, bool unsure = false) {
+ TAutoPtr<IEventHandle> evi(ev.Release());
+ return ForwardOnNondelivery(evi, reason, unsure);
+ }
+
+ TActorId GetForwardOnNondeliveryRecipient() const;
+ };
+
+ // fat handle
+ class IEventHandleFat : public IEventHandle, TNonCopyable {
public:
template <typename TEv>
- inline TEv* CastAsLocal() const noexcept {
+ inline TEv* CastAsLocal() const noexcept { // cast with event check
auto fits = GetTypeRewrite() == TEv::EventType;
+ constexpr bool couldBeCasted = requires() {static_cast<TEv*>(Event.Get());};
+ if constexpr (couldBeCasted) {
+ return fits ? static_cast<TEv*>(Event.Get()) : nullptr;
+ } else {
+ Y_FAIL("Event type %" PRIu32 " couldn't be converted to type %s", Type, TypeName<TEv>().data());
+ }
+ }
- return fits ? static_cast<TEv*>(Event.Get()) : nullptr;
+ template <typename TEv>
+ inline TEv* StaticCastAsLocal() const noexcept { // blind cast
+ constexpr bool couldBeCasted = requires() {static_cast<TEv*>(Event.Get());};
+ if constexpr (couldBeCasted) {
+ return static_cast<TEv*>(Event.Get());
+ } else {
+ Y_FAIL("Event type %" PRIu32 " couldn't be converted to type %s", Type, TypeName<TEv>().data());
+ }
}
template <typename TEventType>
TEventType* Get() {
if (Type != TEventType::EventType)
- Y_FAIL("Event type %" PRIu32 " doesn't match the expected type %" PRIu32, Type, TEventType::EventType);
+ Y_FAIL("%s", (TStringBuilder()
+ << "Event type " << Type
+ << " doesn't match the expected type " << TEventType::EventType
+ << " requested typename " << TypeName<TEventType>()
+ << " actual typename " << GetTypeName()).data());
- if (!Event) {
+ constexpr bool couldBeGot = requires() {
Event.Reset(TEventType::Load(Buffer.Get()));
+ static_cast<TEventType*>(Event.Get());
+ };
+ if constexpr (couldBeGot) {
+ if (!Event) {
+ Event.Reset(TEventType::Load(Buffer.Get()));
+ }
+
+ if (Event) {
+ return static_cast<TEventType*>(Event.Get());
+ }
+
+ Y_FAIL("Failed to Load() event type %" PRIu32 " class %s", Type, TypeName<TEventType>().data());
+ } else {
+ Y_FAIL("Event type %" PRIu32 " couldn't be get as type %s", Type, TypeName<TEventType>().data());
}
-
- if (Event) {
- return static_cast<TEventType*>(Event.Get());
- }
-
- Y_FAIL("Failed to Load() event type %" PRIu32 " class %s", Type, TypeName<TEventType>().data());
}
template <typename T>
@@ -96,104 +273,43 @@ namespace NActors {
return x;
}
- enum EFlags {
- FlagTrackDelivery = 1 << 0,
- FlagForwardOnNondelivery = 1 << 1,
- FlagSubscribeOnSession = 1 << 2,
- FlagUseSubChannel = 1 << 3,
- FlagGenerateUnsureUndelivered = 1 << 4,
- FlagExtendedFormat = 1 << 5,
- };
-
- const ui32 Type;
- const ui32 Flags;
- const TActorId Recipient;
- const TActorId Sender;
- const ui64 Cookie;
const TScopeId OriginScopeId = TScopeId::LocallyGenerated; // filled in when the message is received from Interconnect
- // if set, used by ActorSystem/Interconnect to report tracepoints
- NWilson::TTraceId TraceId;
-
// filled if feeded by interconnect session
const TActorId InterconnectSession;
-#ifdef ACTORSLIB_COLLECT_EXEC_STATS
- ::NHPTimer::STime SendTime;
-#endif
-
- static const size_t ChannelBits = 12;
- static const size_t ChannelShift = (sizeof(ui32) << 3) - ChannelBits;
#ifdef USE_ACTOR_CALLSTACK
TCallstack Callstack;
#endif
- ui16 GetChannel() const noexcept {
- return Flags >> ChannelShift;
- }
-
- ui64 GetSubChannel() const noexcept {
- return Flags & FlagUseSubChannel ? Sender.LocalId() : 0ULL;
- }
-
- static ui32 MakeFlags(ui32 channel, ui32 flags) {
- Y_VERIFY(channel < (1 << ChannelBits));
- Y_VERIFY(flags < (1 << ChannelShift));
- return (flags | (channel << ChannelShift));
- }
-
private:
THolder<IEventBase> Event;
TIntrusivePtr<TEventSerializedData> Buffer;
- TActorId RewriteRecipient;
- ui32 RewriteType;
-
- THolder<TOnNondelivery> OnNondeliveryHolder; // only for local events
-
public:
- void Rewrite(ui32 typeRewrite, TActorId recipientRewrite) {
- RewriteRecipient = recipientRewrite;
- RewriteType = typeRewrite;
- }
-
- void DropRewrite() {
- RewriteRecipient = Recipient;
- RewriteType = Type;
- }
-
- const TActorId& GetRecipientRewrite() const {
- return RewriteRecipient;
- }
-
- ui32 GetTypeRewrite() const {
- return RewriteType;
- }
-
TActorId GetForwardOnNondeliveryRecipient() const {
return OnNondeliveryHolder.Get() ? OnNondeliveryHolder->Recipient : TActorId();
}
- IEventHandle(const TActorId& recipient, const TActorId& sender, IEventBase* ev, ui32 flags = 0, ui64 cookie = 0,
+ IEventHandleFat(const TActorId& recipient, const TActorId& sender, IEventBase* ev, ui32 flags = 0, ui64 cookie = 0,
const TActorId* forwardOnNondelivery = nullptr, NWilson::TTraceId traceId = {})
- : Type(ev->Type())
- , Flags(flags)
- , Recipient(recipient)
- , Sender(sender)
- , Cookie(cookie)
- , TraceId(std::move(traceId))
-#ifdef ACTORSLIB_COLLECT_EXEC_STATS
- , SendTime(0)
-#endif
+ : IEventHandle({
+ .Recipient = recipient,
+ .Sender = sender,
+ .Type = ev->Type(),
+ .Flags = flags,
+ .Cookie = cookie,
+ .RewriteRecipient = recipient,
+ .RewriteType = ev->Type(),
+ .TraceId = std::move(traceId),
+ })
, Event(ev)
- , RewriteRecipient(Recipient)
- , RewriteType(Type)
{
if (forwardOnNondelivery)
OnNondeliveryHolder.Reset(new TOnNondelivery(*forwardOnNondelivery));
}
- IEventHandle(ui32 type,
+ IEventHandleFat(ui32 type,
ui32 flags,
const TActorId& recipient,
const TActorId& sender,
@@ -201,25 +317,24 @@ namespace NActors {
ui64 cookie,
const TActorId* forwardOnNondelivery = nullptr,
NWilson::TTraceId traceId = {})
- : Type(type)
- , Flags(flags)
- , Recipient(recipient)
- , Sender(sender)
- , Cookie(cookie)
- , TraceId(std::move(traceId))
-#ifdef ACTORSLIB_COLLECT_EXEC_STATS
- , SendTime(0)
-#endif
+ : IEventHandle({
+ .Recipient = recipient,
+ .Sender = sender,
+ .Type = type,
+ .Flags = flags,
+ .Cookie = cookie,
+ .RewriteRecipient = recipient,
+ .RewriteType = type,
+ .TraceId = std::move(traceId),
+ })
, Buffer(std::move(buffer))
- , RewriteRecipient(Recipient)
- , RewriteType(Type)
{
if (forwardOnNondelivery)
OnNondeliveryHolder.Reset(new TOnNondelivery(*forwardOnNondelivery));
}
// Special ctor for events from interconnect.
- IEventHandle(const TActorId& session,
+ IEventHandleFat(const TActorId& session,
ui32 type,
ui32 flags,
const TActorId& recipient,
@@ -228,20 +343,19 @@ namespace NActors {
ui64 cookie,
TScopeId originScopeId,
NWilson::TTraceId traceId) noexcept
- : Type(type)
- , Flags(flags)
- , Recipient(recipient)
- , Sender(sender)
- , Cookie(cookie)
+ : IEventHandle({
+ .Recipient = recipient,
+ .Sender = sender,
+ .Type = type,
+ .Flags = flags,
+ .Cookie = cookie,
+ .RewriteRecipient = recipient,
+ .RewriteType = type,
+ .TraceId = std::move(traceId),
+ })
, OriginScopeId(originScopeId)
- , TraceId(std::move(traceId))
, InterconnectSession(session)
-#ifdef ACTORSLIB_COLLECT_EXEC_STATS
- , SendTime(0)
-#endif
, Buffer(std::move(buffer))
- , RewriteRecipient(Recipient)
- , RewriteType(Type)
{
}
@@ -286,28 +400,267 @@ namespace NActors {
TAutoPtr<IEventHandle> Forward(const TActorId& dest) {
if (Event)
- return new IEventHandle(dest, Sender, Event.Release(), Flags, Cookie, nullptr, std::move(TraceId));
+ return new IEventHandleFat(dest, Sender, Event.Release(), Flags, Cookie, nullptr, std::move(TraceId));
else
- return new IEventHandle(Type, Flags, dest, Sender, Buffer, Cookie, nullptr, std::move(TraceId));
+ return new IEventHandleFat(Type, Flags, dest, Sender, Buffer, Cookie, nullptr, std::move(TraceId));
+ }
+
+ static TAutoPtr<IEventHandleFat> MakeFat(TAutoPtr<IEventHandle> ev) {
+ if (ev->IsEventLight()) {
+ Y_FAIL("Can't make light event fat");
+ } else {
+ TAutoPtr<IEventHandleFat> evb(static_cast<IEventHandleFat*>(ev.Release()));
+ return evb;
+ }
}
- TAutoPtr<IEventHandle> ForwardOnNondelivery(ui32 reason, bool unsure = false);
+ static IEventHandleFat* GetFat(IEventHandle* ev) {
+ if (ev->IsEventLight()) {
+ Y_FAIL("Can't make light event fat");
+ } else {
+ return static_cast<IEventHandleFat*>(ev);
+ }
+ }
+
+ static const IEventHandleFat* GetFat(const IEventHandle* ev) {
+ if (ev->IsEventLight()) {
+ Y_FAIL("Can't make light event fat");
+ } else {
+ return static_cast<const IEventHandleFat*>(ev);
+ }
+ }
+
+ static IEventHandleFat* GetFat(TAutoPtr<IEventHandle>& ev) {
+ return GetFat(ev.Get());
+ }
+
+ static IEventHandleFat* GetFat(THolder<IEventHandle>& ev) {
+ return GetFat(ev.Get());
+ }
+
+ static IEventHandleFat* GetFat(std::unique_ptr<IEventHandle>& ev) {
+ return GetFat(ev.get());
+ }
+
+ static TAutoPtr<IEventHandle> MakeBase(TAutoPtr<IEventHandleFat> ev) {
+ return ev.Release();
+ }
+
+ static std::unique_ptr<IEventHandle> ForwardOnNondelivery(std::unique_ptr<IEventHandleFat>& ev, ui32 reason, bool unsure = false);
};
template <typename TEventType>
- class TEventHandle: public IEventHandle {
- TEventHandle(); // we never made instance of TEventHandle
+ class TEventHandleFat: public IEventHandleFat {
+ TEventHandleFat(); // we never made instance of TEventHandleFat
public:
TEventType* Get() {
- return IEventHandle::Get<TEventType>();
+ return IEventHandleFat::Get<TEventType>();
}
TAutoPtr<TEventType> Release() {
- return IEventHandle::Release<TEventType>();
+ return IEventHandleFat::Release<TEventType>();
+ }
+ };
+
+ static_assert(sizeof(TEventHandleFat<IEventBase>) == sizeof(IEventHandleFat), "expect sizeof(TEventHandleFat<IEventBase>) == sizeof(IEventHandleFat)");
+
+ // light handle
+ class IEventHandleLight : public IEventHandle {
+ public:
+ IEventHandleLight(ui32 type) {
+ RewriteType = Type = type;
+ Light = true;
+ }
+
+ IEventHandleLight* PrepareSend(TActorId recipient, TActorId sender) {
+ RewriteRecipient = Recipient = recipient;
+ Sender = sender;
+ return this;
+ }
+
+ IEventHandleLight* PrepareSend(TActorId recipient, TActorId sender, ui32 flags) {
+ RewriteRecipient = Recipient = recipient;
+ Sender = sender;
+ SetFlags(flags);
+ return this;
+ }
+
+ IEventHandleLight* PrepareSend(TActorId recipient, TActorId sender, ui32 flags, ui64 cookie) {
+ RewriteRecipient = Recipient = recipient;
+ Sender = sender;
+ SetFlags(flags);
+ Cookie = cookie;
+ return this;
+ }
+
+ IEventHandleLight* PrepareSend(TActorId recipient, TActorId sender, ui32 flags, ui64 cookie, NWilson::TTraceId traceId) {
+ RewriteRecipient = Recipient = recipient;
+ Sender = sender;
+ SetFlags(flags);
+ Cookie = cookie;
+ TraceId = std::move(traceId);
+ return this;
+ }
+
+ void Forward(const TActorId& dest) {
+ RewriteRecipient = dest;
+ }
+
+ static IEventHandleLight* GetLight(IEventHandle* ev) {
+ if (ev->IsEventLight()) {
+ return static_cast<IEventHandleLight*>(ev);
+ } else {
+ Y_FAIL("Can't make fat event light");
+ }
+ }
+
+ static IEventHandleLight* GetLight(TAutoPtr<IEventHandle>& ev) {
+ return GetLight(ev.Get());
+ }
+
+ static IEventHandleLight* GetLight(THolder<IEventHandle>& ev) {
+ return GetLight(ev.Get());
+ }
+
+ static IEventHandleLight* GetLight(std::unique_ptr<IEventHandle>& ev) {
+ return GetLight(ev.get());
+ }
+
+ static IEventHandleLight* ReleaseLight(TAutoPtr<IEventHandle>& ev) {
+ return GetLight(ev.Release());
+ }
+
+ static std::unique_ptr<IEventHandle> ForwardOnNondelivery(std::unique_ptr<IEventHandleLight>& ev, ui32 reason, bool unsure = false);
+
+ template<typename TEventType>
+ TEventType* Get() {
+ if (Type != TEventType::EventType) {
+ Y_FAIL("Event type %" PRIu32 " doesn't match the expected type %" PRIu32, Type, TEventType::EventType);
+ }
+ constexpr bool couldBeConverted = requires() {static_cast<TEventType*>(this);};
+ if constexpr (couldBeConverted) {
+ return static_cast<TEventType*>(this);
+ } else {
+ Y_FAIL("Event type %" PRIu32 " couldn't be converted to type %s", Type, TypeName<TEventType>().data());
+ }
+ }
+
+ template<typename TEventType>
+ TEventType* CastAsLocal() {
+ constexpr bool couldBeConverted = requires() {static_cast<TEventType*>(this);};
+ if constexpr (couldBeConverted) {
+ if (Type == TEventType::EventType) {
+ return static_cast<TEventType*>(this);
+ }
+ }
+ return nullptr;
+ }
+
+ template<typename TEventType>
+ TEventType* StaticCastAsLocal() {
+ constexpr bool couldBeConverted = requires() {static_cast<TEventType*>(this);};
+ if constexpr (couldBeConverted) {
+ return static_cast<TEventType*>(this);
+ }
+ Y_FAIL("Event type %" PRIu32 " couldn't be converted to type %s", Type, TypeName<TEventType>().data());
}
};
- static_assert(sizeof(TEventHandle<IEventBase>) == sizeof(IEventHandle), "expect sizeof(TEventHandle<IEventBase>) == sizeof(IEventHandle)");
+ template<typename TEventType>
+ TEventType* IEventHandle::Get() {
+ if (IsEventLight()) {
+ return IEventHandleLight::GetLight(this)->Get<TEventType>();
+ } else {
+ return IEventHandleFat::GetFat(this)->Get<TEventType>();
+ }
+ }
+
+ template<typename TEventType>
+ TEventType* IEventHandle::CastAsLocal() {
+ if (IsEventLight()) {
+ return IEventHandleLight::GetLight(this)->CastAsLocal<TEventType>();
+ } else {
+ return IEventHandleFat::GetFat(this)->CastAsLocal<TEventType>();
+ }
+ }
+
+ template<typename TEventType>
+ TEventType* IEventHandle::StaticCastAsLocal() {
+ if (IsEventLight()) {
+ return IEventHandleLight::GetLight(this)->StaticCastAsLocal<TEventType>();
+ } else {
+ return IEventHandleFat::GetFat(this)->StaticCastAsLocal<TEventType>();
+ }
+ }
+
+ template<typename TEventType>
+ TEventType* IEventHandle::Release(TAutoPtr<IEventHandle>& ev) {
+ if (ev->IsEventLight()) {
+ return IEventHandleLight::GetLight(ev.Release())->CastAsLocal<TEventType>();
+ } else {
+ return IEventHandleFat::GetFat(ev.Get())->Release<TEventType>().Release();
+ }
+ }
+
+ template<typename TEventType>
+ TEventType* IEventHandle::Release(THolder<IEventHandle>& ev) {
+ if (ev->IsEventLight()) {
+ return IEventHandleLight::GetLight(ev.Release())->CastAsLocal<TEventType>();
+ } else {
+ return IEventHandleFat::GetFat(ev.Get())->Release<TEventType>().Release();
+ }
+ }
+
+ template<typename TEventType>
+ TEventType* IEventHandle::Release(std::unique_ptr<IEventHandle>& ev) {
+ if (ev->IsEventLight()) {
+ return IEventHandleLight::GetLight(ev.release())->CastAsLocal<TEventType>();
+ } else {
+ return IEventHandleFat::GetFat(ev.get())->Release<TEventType>().Release();
+ }
+ }
+
+
+ class IEventHandleLightSerializable;
+
+ using TEventSerializer = std::function<bool(const IEventHandleLightSerializable*, TChunkSerializer*)>;
+
+ class IEventHandleLightSerializable : public IEventHandleLight {
+ public:
+ TEventSerializer Serializer;
+
+ IEventHandleLightSerializable(ui32 type, TEventSerializer serializer)
+ : IEventHandleLight(type)
+ , Serializer(std::move(serializer))
+ {
+ Serializable = true;
+ }
+
+ static IEventHandleLightSerializable* GetLightSerializable(IEventHandle* ev) {
+ if (ev->IsEventSerializable()) {
+ return static_cast<IEventHandleLightSerializable*>(ev);
+ } else {
+ Y_FAIL("Can't make serializable event");
+ }
+ }
+
+ static const IEventHandleLightSerializable* GetLightSerializable(const IEventHandle* ev) {
+ if (ev->IsEventSerializable()) {
+ return static_cast<const IEventHandleLightSerializable*>(ev);
+ } else {
+ Y_FAIL("Can't make serializable event");
+ }
+ }
+
+ static IEventHandleLightSerializable* GetLightSerializable(TAutoPtr<IEventHandle>& ev) {
+ return GetLightSerializable(ev.Get());
+ }
+
+ size_t GetSize() const {
+ // TODO(xenoxeno)
+ return 0;
+ }
+ };
template <typename TEventType, ui32 EventType0>
class TEventBase: public IEventBase {
@@ -318,7 +671,7 @@ namespace NActors {
}
// still abstract
- typedef TEventHandle<TEventType> THandle;
+ typedef TEventHandleFat<TEventType> THandle;
typedef TAutoPtr<THandle> TPtr;
};
@@ -327,7 +680,7 @@ namespace NActors {
return TString(header); \
} \
bool SerializeToArcadiaStream(NActors::TChunkSerializer*) const override { \
- Y_FAIL("Local event " #eventType " is not serializable"); \
+ Y_FAIL("Local event %s is not serializable", TypeName(*this).data()); \
} \
static IEventBase* Load(NActors::TEventSerializedData*) { \
Y_FAIL("Local event " #eventType " has no load method"); \
@@ -349,4 +702,39 @@ namespace NActors {
bool IsSerializable() const override { \
return true; \
}
+
+
+ struct TEventMeta {
+ TActorId Session;
+ ui32 Type;
+ ui32 Flags;
+ TActorId Recipient;
+ TActorId Sender;
+ ui64 Cookie;
+ TScopeId OriginScopeId;
+ NWilson::TTraceId TraceId;
+ TRope Data;
+
+ bool IsExtendedFormat() const {
+ return Flags & IEventHandle::FlagExtendedFormat;
+ }
+ };
+
+ inline constexpr ui32 GetEventSpace(ui32 eventType) {
+ return (eventType >> 16u);
+ }
+
+ inline constexpr ui32 GetEventSubType(ui32 eventType) {
+ return (eventType & (0xffff));
+ }
+
+ struct IEventFactory {
+ virtual IEventHandle* Construct(const TEventMeta& eventMeta) = 0;
+ virtual void Destruct(IEventHandle*) = 0;
+ };
+
+ struct TEventFactories {
+ // it supposed to be statically allocated in the begining
+ static std::vector<std::vector<IEventFactory*>*> EventFactories; // [EventSpace][EventSubType]
+ };
}