diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2024-03-06 07:25:32 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2024-03-06 07:35:05 +0300 |
commit | 83ebfa17c1534617b0b00d1b94f063c46956173a (patch) | |
tree | 506d2bacc170deab518fe249ece7d6b2b6c2e32a | |
parent | 5592bf3a659161d8c9af4d5eda23171aa1a5ebf3 (diff) | |
download | ydb-83ebfa17c1534617b0b00d1b94f063c46956173a.tar.gz |
Intermediate changes
-rw-r--r-- | yt/yt/core/actions/bind-inl.h | 163 | ||||
-rw-r--r-- | yt/yt/core/actions/unittests/bind_ut.cpp | 55 |
2 files changed, 157 insertions, 61 deletions
diff --git a/yt/yt/core/actions/bind-inl.h b/yt/yt/core/actions/bind-inl.h index f88d3116d9..d4c2072eb3 100644 --- a/yt/yt/core/actions/bind-inl.h +++ b/yt/yt/core/actions/bind-inl.h @@ -21,7 +21,7 @@ public: : T_(x) { } - T* Get() const + T* Unwrap() const { return T_; } @@ -49,7 +49,7 @@ public: delete T_; } - T* Get() const + T* Unwrap() const { return T_; } @@ -81,7 +81,7 @@ public: other.IsValid_ = false; } - T&& Get() const + T&& Unwrap() const { YT_ASSERT(IsValid_); IsValid_ = false; @@ -101,7 +101,7 @@ public: : T_(&x) { } - const T& Get() const + const T& Unwrap() const { return *T_; } @@ -113,33 +113,33 @@ private: //////////////////////////////////////////////////////////////////////////////// template <class T> -inline const T& Unwrap(T& value) +const T& Unwrap(T& value) { return value; } template <class T> -inline T* Unwrap(const TUnretainedWrapper<T>& wrapper) +T* Unwrap(const TUnretainedWrapper<T>& wrapper) { - return wrapper.Get(); + return wrapper.Unwrap(); } template <class T> -inline T* Unwrap(const TOwnedWrapper<T>& wrapper) +T* Unwrap(const TOwnedWrapper<T>& wrapper) { - return wrapper.Get(); + return wrapper.Unwrap(); } template <class T> -inline T&& Unwrap(const TPassedWrapper<T>& wrapper) +T&& Unwrap(const TPassedWrapper<T>& wrapper) { - return wrapper.Get(); + return wrapper.Unwrap(); } template <class T> -inline const T& Unwrap(const TConstRefWrapper<T>& wrapper) +const T& Unwrap(const TConstRefWrapper<T>& wrapper) { - return wrapper.Get(); + return wrapper.Unwrap(); } //////////////////////////////////////////////////////////////////////////////// @@ -152,7 +152,26 @@ public: : Functor_(functor) { } - T& Get() + T& Unwrap() + { + return Functor_; + } + +private: + T Functor_; +}; + +//////////////////////////////////////////////////////////////////////////////// + +template <class T> +class TThrowOnDestroyedWrapper +{ +public: + explicit TThrowOnDestroyedWrapper(const T& functor) + : Functor_(functor) + { } + + T& Unwrap() { return Functor_; } @@ -166,43 +185,49 @@ private: //////////////////////////////////////////////////////////////////////////////// template <class T> -static auto IgnoreResult(const T& x) +auto IgnoreResult(const T& x) { return NYT::NDetail::TIgnoreResultWrapper<T>(x); } template <class T> -static auto Unretained(T* x) +auto ThrowOnDestroyed(const T& x) +{ + return NYT::NDetail::TThrowOnDestroyedWrapper<T>(x); +} + +template <class T> +auto Unretained(T* x) { return NYT::NDetail::TUnretainedWrapper<T>(x); } template <class T> -static auto Owned(T* x) +auto Owned(T* x) { return NYT::NDetail::TOwnedWrapper<T>(x); } template <class T> -static auto Passed(T&& x) +auto Passed(T&& x) { return NYT::NDetail::TPassedWrapper<T>(std::forward<T>(x)); } template <class T> -static auto ConstRef(const T& x) +auto ConstRef(const T& x) { return NYT::NDetail::TConstRefWrapper<T>(x); } template <class U> -static U& WrapToPassed(U& arg) +U& WrapToPassed(U& arg) { return arg; } template <class U> -static auto WrapToPassed(U&& arg) +auto WrapToPassed(U&& arg) { return Passed(std::move(arg)); } @@ -223,38 +248,35 @@ public: { } template <class D, class... XAs> - auto operator()(D* object, XAs&&... args) const + auto operator()(D* this_, XAs&&... args) const { static_assert( !std::is_array_v<D>, "First bound argument to a method cannot be an array"); - return (object->*Method_)(std::forward<XAs>(args)...); + return (this_->*Method_)(std::forward<XAs>(args)...); } template <class D, class... XAs> - void operator()(const TWeakPtr<D>& ref, XAs&&... args) const + void operator()(const TWeakPtr<D>& weakThis, XAs&&... args) const { using TResult = typename TFunctorTraits<TMethod>::TResult; static_assert( std::is_void_v<TResult>, "Weak calls are only supported for methods with a void return type"); - auto strongRef = ref.Lock(); - auto* object = strongRef.Get(); - - if (!object) { + auto strongThis = weakThis.Lock(); + if (!strongThis) { return; } - (object->*Method_)(std::forward<XAs>(args)...); + (strongThis.Get()->*Method_)(std::forward<XAs>(args)...); } template <class D, class... XAs> - auto operator()(const TIntrusivePtr<D>& ref, XAs&&... args) const + auto operator()(const TIntrusivePtr<D>& this_, XAs&&... args) const { - auto* object = ref.Get(); - return (object->*Method_)(std::forward<XAs>(args)...); + return (this_.Get()->*Method_)(std::forward<XAs>(args)...); } private: @@ -350,13 +372,13 @@ struct TFunctorTraits<TR (C::*)(TAs...) const noexcept> //////////////////////////////////////////////////////////////////////////////// template <class T> -class TOmitResultInvoker +class TIgnoreResultInvoker { public: using TInvoker = typename TFunctorTraits<T>::TInvoker; - explicit TOmitResultInvoker(NDetail::TIgnoreResultWrapper<T>&& invoker) - : Invoker_(std::move(invoker.Get())) + explicit TIgnoreResultInvoker(NDetail::TIgnoreResultWrapper<T>&& wrapper) + : Invoker_(std::move(wrapper.Unwrap())) { } template <class... XAs> @@ -372,12 +394,69 @@ private: template <class T> struct TFunctorTraits<NDetail::TIgnoreResultWrapper<T>> { - using TInvoker = TOmitResultInvoker<T>; + using TInvoker = TIgnoreResultInvoker<T>; using TSignature = typename TToVoidSignature<typename TFunctorTraits<T>::TSignature>::TType; }; //////////////////////////////////////////////////////////////////////////////// +template <class TMethod> +class TThrowOnDestroyedInvoker +{ +public: + explicit TThrowOnDestroyedInvoker(NDetail::TThrowOnDestroyedWrapper<TMethod>&& wrapper) + : Method_(wrapper.Unwrap()) + { } + + template <class D, class... XAs> + auto operator()(const TWeakPtr<D>& weakThis, XAs&&... args) const + { + auto strongThis = weakThis.Lock(); + if (!strongThis) { + THROW_ERROR_EXCEPTION(NYT::EErrorCode::Canceled, "Object destroyed"); + } + + return (strongThis.Get()->*Method_)(std::forward<XAs>(args)...); + } + +private: + const TMethod Method_; +}; + +template <class TR, class C, class... TAs> +struct TFunctorTraits<NDetail::TThrowOnDestroyedWrapper<TR (C::*)(TAs...)>> +{ + using TInvoker = TThrowOnDestroyedInvoker<TR (C::*)(TAs...)>; + using TSignature = TR (C*, TAs...); + using TResult = TR; +}; + +template <class TR, class C, class... TAs> +struct TFunctorTraits<NDetail::TThrowOnDestroyedWrapper<TR (C::*)(TAs...) const>> +{ + using TInvoker = TThrowOnDestroyedInvoker<TR (C::*)(TAs...) const>; + using TSignature = TR (C*, TAs...); + using TResult = TR; +}; + +template <class TR, class C, class... TAs> +struct TFunctorTraits<NDetail::TThrowOnDestroyedWrapper<TR (C::*)(TAs...) noexcept>> +{ + using TInvoker = TThrowOnDestroyedInvoker<TR (C::*)(TAs...) noexcept>; + using TSignature = TR (C*, TAs...); + using TResult = TR; +}; + +template <class TR, class C, class... TAs> +struct TFunctorTraits<NDetail::TThrowOnDestroyedWrapper<TR (C::*)(TAs...) const noexcept>> +{ + using TInvoker = TThrowOnDestroyedInvoker<TR (C::*)(TAs...) const noexcept>; + using TSignature = TR (C*, TAs...); + using TResult = TR; +}; + +//////////////////////////////////////////////////////////////////////////////// + template <class T> struct TIsNonConstReference : public std::false_type @@ -489,8 +568,8 @@ public: location #endif ) - , Functor(std::forward<XFunctor>(functor)) - , BoundArgs(std::forward<XBs>(boundArgs)...) + , Functor_(std::forward<XFunctor>(functor)) + , BoundArgs_(std::forward<XBs>(boundArgs)...) { } // Keep minimum frame count. @@ -507,14 +586,14 @@ public: auto propagatingStorageGuard = state->MakePropagatingStorageGuard(); Y_UNUSED(propagatingStorageGuard); - return state->Functor( - NDetail::Unwrap(std::get<BoundIndexes>(state->BoundArgs))..., + return state->Functor_( + NDetail::Unwrap(std::get<BoundIndexes>(state->BoundArgs_))..., std::forward<TAs>(args)...); } private: - TFunctor Functor; - const std::tuple<TBs...> BoundArgs; + TFunctor Functor_; + const std::tuple<TBs...> BoundArgs_; }; //////////////////////////////////////////////////////////////////////////////// diff --git a/yt/yt/core/actions/unittests/bind_ut.cpp b/yt/yt/core/actions/unittests/bind_ut.cpp index 6abad98bc8..3b0fe90989 100644 --- a/yt/yt/core/actions/unittests/bind_ut.cpp +++ b/yt/yt/core/actions/unittests/bind_ut.cpp @@ -93,10 +93,10 @@ class TObjectWithFullRC , public TRefCounted { }; -using TObjectWithExtrinsicRCPtr = TIntrusivePtr<TObjectWithFullRC>; -using TObjectWithExtrinsicRCConstPtr = TIntrusivePtr<const TObjectWithFullRC>; -using TObjectWithExtrinsicRCWkPtr = TWeakPtr<TObjectWithFullRC>; -using TObjectWithExtrinsicRCConstWkPtr = TWeakPtr<const TObjectWithFullRC>; +using TObjectWithFullRCPtr = TIntrusivePtr<TObjectWithFullRC>; +using TObjectWithFullRCConstPtr = TIntrusivePtr<const TObjectWithFullRC>; +using TObjectWithFullRCWkPtr = TWeakPtr<TObjectWithFullRC>; +using TObjectWithFullRCConstWkPtr = TWeakPtr<const TObjectWithFullRC>; // Below there is a series of either reference-counted or not classes // with simple inheritance and both virtual and non-virtual methods. @@ -700,43 +700,60 @@ TEST_F(TBindTest, UnretainedWrapper) // not canceled. TEST_F(TBindTest, WeakPtr) { - TObjectWithExtrinsicRCPtr object = New<TObjectWithFullRC>(); - TObjectWithExtrinsicRCWkPtr objectWk(object); + TObjectWithFullRCPtr object = New<TObjectWithFullRC>(); + TObjectWithFullRCWkPtr objectWk(object); EXPECT_CALL(*object, VoidMethod0()); + EXPECT_CALL(*object, IntMethod0()).WillOnce(Return(42)); + EXPECT_CALL(*object, IntConstMethod0()).WillOnce(Return(13)); EXPECT_CALL(*object, VoidConstMethod0()).Times(2); - TClosure boundMethod = + TClosure voidMethod = BIND( &TObjectWithFullRC::VoidMethod0, - TObjectWithExtrinsicRCWkPtr(object)); - boundMethod(); + TObjectWithFullRCWkPtr(object)); + voidMethod(); - TClosure constMethodNonConstObject = + TCallback<int()> intMethod = + BIND( + ThrowOnDestroyed(&TObjectWithFullRC::IntMethod0), + TObjectWithFullRCWkPtr(object)); + EXPECT_EQ(42, intMethod()); + + TCallback<int()> constIntMethodNonConstObject = + BIND( + ThrowOnDestroyed(&TObjectWithFullRC::IntConstMethod0), + TObjectWithFullRCWkPtr(object)); + EXPECT_EQ(13, constIntMethodNonConstObject()); + + TClosure constVoidMethodNonConstObject = BIND( &TObject::VoidConstMethod0, - TObjectWithExtrinsicRCWkPtr(object)); - constMethodNonConstObject(); + TObjectWithFullRCWkPtr(object)); + constVoidMethodNonConstObject(); - TClosure constMethodConstObject = + TClosure constVoidMethodConstObject = BIND( &TObject::VoidConstMethod0, - TObjectWithExtrinsicRCConstWkPtr(object)); - constMethodConstObject(); + TObjectWithFullRCConstWkPtr(object)); + constVoidMethodConstObject(); TCallback<int(int)> normalFunc = BIND( &FunctionWithWeakParam<TObjectWithFullRC>, - TObjectWithExtrinsicRCWkPtr(object)); + TObjectWithFullRCWkPtr(object)); EXPECT_EQ(1, normalFunc(1)); object.Reset(); ASSERT_TRUE(objectWk.IsExpired()); - boundMethod(); - constMethodNonConstObject(); - constMethodConstObject(); + voidMethod(); + constVoidMethodNonConstObject(); + constVoidMethodConstObject(); + + EXPECT_THROW_WITH_ERROR_CODE(intMethod(), NYT::EErrorCode::Canceled); + EXPECT_THROW_WITH_ERROR_CODE(constIntMethodNonConstObject(), NYT::EErrorCode::Canceled); EXPECT_EQ(2, normalFunc(2)); } |