104 using DelegateFunction = TReturnValue(*)(TArgs..., Args2...);
107 : Function(InFunction)
108 , Payload(std::forward<Args2>(InPayload)...)
112 LStaticDelegate(DelegateFunction InFunction,
const std::tuple<Args2...>& InPayload)
113 : Function(InFunction)
118 FORCEINLINE
virtual TReturnValue Execute(TArgs&&... Args)
override
120 return Execute_Internal(std::forward<TArgs>(Args)..., std::index_sequence_for<Args2...>());
123 virtual void Clone(
void* Destination)
override
129 template<std::size_t... Is>
130 FORCEINLINE TReturnValue Execute_Internal(TArgs&&... Args, std::index_sequence<Is...>)
132 return Function(std::forward<TArgs>(Args)..., std::get<Is>(Payload)...);
135 DelegateFunction Function;
136 std::tuple<Args2...> Payload;
155 using DelegateFunction =
typename Core::MemberFunction<bIsConst, T, TReturnValue, TArgs..., Args2...>::type;
157 LRawDelegate(T* InObjectRef, DelegateFunction InFunction, Args2&&... InPayload)
158 : ObjectRef(InObjectRef)
159 , Function(InFunction)
160 , Payload(std::forward<Args2>(InPayload)...)
162 LK_CORE_ASSERT(InObjectRef,
"Passed object is nullptr");
163 LK_CORE_ASSERT(InFunction,
"Passed function is invalid");
166 LRawDelegate(T* InObjectRef, DelegateFunction InFunction,
const std::tuple<Args2...>& InPayload)
167 : ObjectRef(InObjectRef)
168 , Function(InFunction)
171 LK_CORE_ASSERT(InObjectRef,
"Passed object is nullptr");
172 LK_CORE_ASSERT(InFunction,
"Passed function is invalid");
175 FORCEINLINE
virtual TReturnValue Execute(TArgs&&... Args)
override
177 return Execute_Internal(std::forward<TArgs>(Args)..., std::index_sequence_for<Args2...>());
180 FORCEINLINE
virtual const void* GetOwner()
const override
185 virtual void Clone(
void* Destination)
override
187 new (Destination)
LRawDelegate(ObjectRef, Function, Payload);
191 template<std::size_t... Is>
192 FORCEINLINE TReturnValue Execute_Internal(TArgs&&... Args, std::index_sequence<Is...>)
194 return (ObjectRef->*Function)(std::forward<TArgs>(Args)..., std::get<Is>(Payload)...);
197 T* ObjectRef =
nullptr;
198 DelegateFunction Function;
199 std::tuple<Args2...> Payload;
219 : Lambda(std::forward<TLambda>(InLambda))
220 , Payload(std::forward<Args2>(InPayload)...)
224 explicit LLambdaDelegate(
const TLambda& InLambda,
const std::tuple<Args2...>& InPayload)
230 FORCEINLINE TReturnValue Execute(TArgs&&... Args)
override
232 return Execute_Internal(std::forward<TArgs>(Args)..., std::index_sequence_for<Args2...>());
235 FORCEINLINE
virtual void Clone(
void* Destination)
override
241 template<std::size_t... Is>
242 FORCEINLINE TReturnValue Execute_Internal(TArgs&&... Args, std::index_sequence<Is...>)
244 return (TReturnValue)((Lambda)(std::forward<TArgs>(Args)..., std::get<Is>(Payload)...));
248 std::tuple<Args2...> Payload;
264 using DelegateFunction =
typename Core::MemberFunction<bIsConst, T, TReturnValue, TArgs..., Args2...>::type;
267 const DelegateFunction InFunction,
268 Args2&&... InPayload)
269 : ObjectRef(InObjectRef)
270 , Function(InFunction)
271 , Payload(std::forward<Args2>(InPayload)...)
276 const DelegateFunction InFunction,
277 const std::tuple<Args2...>& InPayload)
278 : ObjectRef(InObjectRef)
279 , Function(InFunction)
284 FORCEINLINE
virtual TReturnValue Execute(TArgs&&... Args)
override
286 return Execute_Internal(std::forward<TArgs>(Args)..., std::index_sequence_for<Args2...>());
289 FORCEINLINE
virtual const void* GetOwner()
const override
291 return (ObjectRef.expired() ?
nullptr : ObjectRef.lock().get());
294 FORCEINLINE
virtual void Clone(
void* Destination)
override
300 template<std::size_t... Is>
301 TReturnValue Execute_Internal(TArgs&&... Args, std::index_sequence<Is...>)
303 if (ObjectRef.expired())
305 return TReturnValue();
309 std::shared_ptr<T> Object = ObjectRef.lock();
310 return (Object.get()->*Function)(std::forward<TArgs>(Args)..., std::get<Is>(Payload)...);
314 std::weak_ptr<T> ObjectRef;
315 DelegateFunction Function;
316 std::tuple<Args2...> Payload;
582 if (Other.Allocator.HasAllocation())
584 Allocator.
Allocate(Other.Allocator.GetSize());
590 : Allocator(std::move(Other.Allocator))
599 return Allocator.HasAllocation();
606 if (Other.Allocator.HasAllocation())
608 Allocator.
Allocate(Other.Allocator.GetSize());
615 LDelegateBase& operator=(LDelegateBase&& Other)
noexcept
618 Allocator = std::move(Other.Allocator);
623 FORCEINLINE
const void* GetOwner()
const
625 return (Allocator.HasAllocation() ? GetDelegate()->GetOwner() :
nullptr);
628 FORCEINLINE
size_t GetSize()
const
630 return Allocator.GetSize();
633 FORCEINLINE
void ClearIfBoundTo(
void* InObject)
635 if (InObject && IsBoundTo(InObject))
641 FORCEINLINE
void Clear()
646 FORCEINLINE
bool IsBoundTo(
void* InObject)
const
648 if (!InObject || !Allocator.HasAllocation())
653 return (GetDelegate()->GetOwner() == InObject);
657 FORCEINLINE
void Release()
659 if (Allocator.HasAllocation())
661 GetDelegate()->~IDelegateBase();
666 IDelegateBase* GetDelegate()
const
668 return static_cast<IDelegateBase*
>(Allocator.
GetAllocation());
671 LInlineAllocator<DelegateCore::INLINE_ALLOCATION_SIZE> Allocator;
688 template<
typename T,
typename... Args2>
689 using ConstMemberFunction =
typename Core::MemberFunction<
true, T, TReturnValue, TArgs..., Args2...>::type;
691 template<
typename T,
typename... Args2>
692 using NonConstMemberFunction =
typename Core::MemberFunction<
false, T, TReturnValue, TArgs..., Args2...>::type;
702 [[nodiscard]] FORCEINLINE TReturnValue
Execute(TArgs... Args)
const
704 LK_CORE_VERIFY(Allocator.HasAllocation(),
"Delegate '{}' is not bound",
typeid(
this).name());
721 return TReturnValue();
725 template<
typename T,
typename... TArgs2>
726 [[nodiscard]]
static LDelegate CreateRaw(T* InObject, NonConstMemberFunction<T, TArgs2...> InFunction, TArgs2... Args)
729 Handler.Bind_Internal<
LRawDelegate<
false, T, TReturnValue(TArgs...), TArgs2...>>(
732 std::forward<TArgs2>(Args)...
738 template<
typename T,
typename... TArgs2>
739 [[nodiscard]]
static LDelegate CreateRaw(T* InObject, ConstMemberFunction<T, TArgs2...> InFunction, TArgs2... Args)
742 Handler.Bind_Internal<LRawDelegate<
true, T, TReturnValue(TArgs...), TArgs2...>>(InObject, InFunction, std::forward<TArgs2>(Args)...);
746 template<
typename... TArgs2>
747 [[nodiscard]]
static LDelegate CreateStatic(TReturnValue(*InFunction)(TArgs..., TArgs2...), TArgs2... Args)
750 Handler.Bind_Internal<LStaticDelegate<TReturnValue(TArgs...), TArgs2...>>(InFunction, std::forward<TArgs2>(Args)...);
754 template<
typename T,
typename... TArgs2>
755 [[nodiscard]]
static LDelegate CreateShared(
const std::shared_ptr<T>& ObjectRef,
756 NonConstMemberFunction<T, TArgs2...> InFunction,
760 Handler.Bind_Internal<LSharedPtrDelegate<
false, T, TReturnValue(TArgs...), TArgs2...>>(
763 std::forward<TArgs2>(Args)...
769 template<
typename T,
typename... TArgs2>
770 [[nodiscard]]
static LDelegate CreateShared(
const std::shared_ptr<T>& ObjectRef,
771 ConstMemberFunction<T, TArgs2...> InFunction,
775 Handler.Bind_Internal<LSharedPtrDelegate<
true, T, TReturnValue(TArgs...), TArgs2...>>(
778 std::forward<TArgs2>(Args)...
784 template<
typename TLambda,
typename... TArgs2>
785 [[nodiscard]]
static LDelegate CreateLambda(TLambda&& InLambda, TArgs2... Args)
787 using LambdaType = std::decay_t<TLambda>;
789 Handler.Bind_Internal<LLambdaDelegate<LambdaType, TReturnValue(TArgs...), TArgs2...>>(
790 std::forward<LambdaType>(InLambda),
791 std::forward<TArgs2>(Args)...
799 template<
typename T,
typename... TArgs2>
800 void Bind(T* ObjectRef, NonConstMemberFunction<T, TArgs2...> InFunction, TArgs2&&... Args)
802 static_assert(!std::is_const_v<T>,
"Non-const function cannot be bound on a const object");
803 *
this = CreateRaw<T, TArgs2...>(ObjectRef, InFunction, std::forward<TArgs2>(Args)...);
807 template<
typename T,
typename... TArgs2>
808 void Bind(T* ObjectRef, ConstMemberFunction<T, TArgs2...> InFunction, TArgs2&&... Args)
810 *
this = CreateRaw<T, TArgs2...>(ObjectRef, InFunction, std::forward<TArgs2>(Args)...);
814 template<
typename... TArgs2>
815 void Bind(TReturnValue(*InFunction)(TArgs..., TArgs2...), TArgs2&&... Args)
817 *
this = CreateStatic<TArgs2...>(InFunction, std::forward<TArgs2>(Args)...);
821 template<
typename LambdaType,
typename... Args2>
822 void Bind(LambdaType&& InLambda, Args2&&... args)
824 *
this = CreateLambda<LambdaType, Args2...>(std::forward<LambdaType>(InLambda), std::forward<Args2>(args)...);
828 template<
typename T,
typename... Args2>
829 void Bind(std::shared_ptr<T> ObjectRef, NonConstMemberFunction<T, Args2...> InFunction, Args2&&... args)
831 static_assert(!std::is_const_v<T>,
"Attempted to bind a non-const member function on a const object reference");
832 *
this = CreateShared<T, Args2...>(ObjectRef, InFunction, std::forward<Args2>(args)...);
836 template<
typename T,
typename... Args2>
837 void Bind(std::shared_ptr<T> ObjectRef, ConstMemberFunction<T, Args2...> InFunction, Args2&&... args)
839 *
this = CreateShared<T, Args2...>(ObjectRef, InFunction, std::forward<Args2>(args)...);
843 template<
typename T,
typename... TBindArgs>
844 FORCEINLINE
void Bind_Internal(TBindArgs&&... Args)
847 void* AllocPointer = Allocator.
Allocate(
sizeof(T));
848 new (AllocPointer) T(std::forward<TBindArgs>(Args)...);
851 static std::string_view GetStaticName() {
return StaticName; }
855 #if defined(LK_ENGINE_MSVC)
856 template<
typename... TArgs>
857 #elif defined(LK_ENGINE_GCC) || defined(LK_ENGINE_CLANG)
858 template<
typename... TArgs2>
875 template<
typename T,
typename... TArgs2>
876 using ConstMemberFunction =
typename Core::MemberFunction<
true, T, void, TArgs..., TArgs2...>::type;
878 template<
typename T,
typename... TArgs2>
879 using NonConstMemberFunction =
typename Core::MemberFunction<
false, T, void, TArgs..., TArgs2...>::type;
889 : Dispatchers(std::move(Other.Dispatchers))
890 , Locks(std::move(Other.Locks))
898 Dispatchers = std::move(Other.Dispatchers);
899 Locks = std::move(Other.Locks);
912 for (
size_t i = 0; i < Dispatchers.size(); ++i)
914 if (Dispatchers[i].Handle.IsValid())
916 Dispatchers[i].Callback.Execute(Args...);
930 if (Handle.IsValid())
932 for (
size_t i = 0; i < Dispatchers.size(); ++i)
934 if (Dispatchers[i].Handle == Handle)
938 Dispatchers[i].Callback.Clear();
942 std::swap(Dispatchers[i], Dispatchers[Dispatchers.size() - 1]);
943 Dispatchers.pop_back();
964 for (FDelegateHandlerPair& Handler : Dispatchers)
966 Handler.Callback.Clear();
980 FORCEINLINE
size_t GetSize()
const {
return Dispatchers.size(); }
982 FORCEINLINE std::string_view GetName()
const {
return typeid(
decltype(
this)).name(); }
984 FORCEINLINE std::string ToString()
const
987 return LK_FMT_LIB::format(
"\n[Multicast Delegate]\n"
990 TypeName,
typeid(*this).raw_name());
992 return "MulticastDelegate::FIXME";
996 template<
typename T,
typename... TArgs2>
999 return AddHandler(TDelegate::CreateRaw(ObjectRef, InFunction, std::forward<TArgs2>(Args)...));
1003 template<
typename T,
typename... TArgs2>
1006 return AddHandler(TDelegate::CreateRaw(ObjectRef, InFunction, std::forward<TArgs2>(Args)...));
1010 template<
typename LambdaType,
typename... TArgs2>
1013 return AddHandler(TDelegate::CreateLambda(std::forward<LambdaType>(InLambda), std::forward<TArgs2>(LambdaArgs)...));
1017 template<
typename T,
typename... TArgs2>
1018 FDelegateHandle Add(std::shared_ptr<T> ObjectRef, NonConstMemberFunction<T, TArgs2...> InFunction, TArgs2&&... Args)
1020 return AddHandler(TDelegate::CreateShared(ObjectRef, InFunction, std::forward<TArgs2>(Args)...));
1024 template<
typename T,
typename... TArgs2>
1025 FDelegateHandle Add(std::shared_ptr<T> ObjectRef, ConstMemberFunction<T, TArgs2...> InFunction, TArgs2&&... Args)
1027 return AddHandler(TDelegate::CreateShared(ObjectRef, InFunction, std::forward<TArgs2>(Args)...));
1031 template<
typename T,
typename... TArgs2>
1034 return AddHandler(TDelegate::CreateRaw(ObjectRef.Get(), InFunction, std::forward<TArgs2>(Args)...));
1038 template<
typename T,
typename... TArgs2>
1041 return AddHandler(TDelegate::CreateRaw(ObjectRef.Get(), InFunction, std::forward<TArgs2>(Args)...));
1045 template<
typename... TArgs2>
1048 return AddHandler(TDelegate::CreateStatic(InFunction, std::forward<TArgs2>(Args)...));
1052 template<
typename T>
1055 return AddHandler(TDelegate::CreateLambda(std::move(LHS)));
1058 FDelegateHandle operator+=(TDelegate&& InHandler)
noexcept
1060 return AddHandler(std::forward<TDelegate>(InHandler));
1063 bool operator-=(FDelegateHandle& InHandle)
1068 FORCEINLINE FDelegateHandle AddHandler(TDelegate&& Handler)
noexcept
1070 for (
size_t i = 0; i < Dispatchers.size(); ++i)
1072 if (Dispatchers[i].Handle.IsValid() ==
false)
1074 Dispatchers[i] = FDelegateHandlerPair(FDelegateHandle(
true), std::move(Handler));
1076 return Dispatchers[i].Handle;
1080 Dispatchers.emplace_back(FDelegateHandle(
true), std::move(Handler));
1082 return Dispatchers.back().Handle;
1090 FORCEINLINE
void RemoveObject(
void* InObjectRef)
1094 for (
size_t i = 0; i < Dispatchers.size(); ++i)
1096 if (Dispatchers[i].Callback.GetOwner() == InObjectRef)
1100 Dispatchers[i].Callback.Clear();
1104 std::swap(Dispatchers[i], Dispatchers[Dispatchers.size() - 1]);
1105 Dispatchers.pop_back();
1112 FORCEINLINE
bool IsBoundTo(
const FDelegateHandle& Handle)
const
1114 if (Handle.IsValid())
1116 for (
size_t i = 0; i < Dispatchers.size(); ++i)
1118 if (Dispatchers[i].Handle == Handle)
1128 FORCEINLINE
void Compress(
const size_t MaxSpace = 0)
1130 if (IsLocked() ==
false)
1132 size_t ToDelete = 0;
1133 for (
size_t i = 0; i < Dispatchers.size() - ToDelete; i++)
1135 if (!Dispatchers[i].Handle.IsValid())
1137 std::swap(Dispatchers[i], Dispatchers[ToDelete]);
1142 if (ToDelete > MaxSpace)
1144 Dispatchers.resize(Dispatchers.size() - ToDelete);
1150 FORCEINLINE
void Lock()
1155 FORCEINLINE
void Unlock()
1157 LK_CORE_ASSERT(Locks > 0,
"Cannot unlock, locks is {}", Locks);
1166 FORCEINLINE
bool IsLocked()
const {
return (Locks > 0); }
1173 struct FDelegateHandlerPair
1175 FDelegateHandle Handle;
1178 FDelegateHandlerPair()
1183 FDelegateHandlerPair(
const FDelegateHandle& InHandle,
const TDelegate& InCallback)
1185 , Callback(InCallback)
1189 FDelegateHandlerPair(
const FDelegateHandle& InHandle, TDelegate&& InCallback)
1191 , Callback(
std::move(InCallback))
1197 std::vector<FDelegateHandlerPair> Dispatchers{};