From 6f83ec77320318f535ba32555a222a79b1f4ae15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B0=D0=BD=D0=B8=D0=BB?= <119668441+Jiga228@users.noreply.github.com> Date: Tue, 25 Feb 2025 15:26:12 +0700 Subject: [PATCH] Added template input parameter --- Delegate/Delegate.cpp | 34 ------- Delegate/Delegate.h | 202 +++++++++++++++++++++++++++++++++++++----- exemple/main.cpp | 21 +++++ 3 files changed, 201 insertions(+), 56 deletions(-) delete mode 100644 Delegate/Delegate.cpp create mode 100644 exemple/main.cpp diff --git a/Delegate/Delegate.cpp b/Delegate/Delegate.cpp deleted file mode 100644 index 5066edf..0000000 --- a/Delegate/Delegate.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "Delegate.h" - -void Delegate::DelegateDataForFunction::Call(void* data) -{ - func(data); -} - -void Delegate::bind(void(*func)(void*)) -{ - char* str = new char[8]; - const char* ptrToFuncRef = reinterpret_cast(&func); - for (int i = 0; i < 8; ++i) - str[i] = ptrToFuncRef[i]; - - DelegateDataForFunction* data = new DelegateDataForFunction; - data->next = firstElement; - data->func = func; - data->Hash = FNV1a(str, 8); - delete[] str; - - mDelegateList.lock(); - firstElement = data; - mDelegateList.unlock(); -} - -void Delegate::Call(void* data) const -{ - DelegateDataBase* iterator = firstElement; - while (iterator != nullptr) - { - iterator->Call(data); - iterator = iterator->next; - } -} diff --git a/Delegate/Delegate.h b/Delegate/Delegate.h index d56a74a..ea5afc6 100644 --- a/Delegate/Delegate.h +++ b/Delegate/Delegate.h @@ -2,13 +2,14 @@ #include +template class Delegate { struct DelegateDataBase { DelegateDataBase* next = nullptr; long long Hash = 0; - virtual void Call(void*) = 0; + virtual void Call(TypeParameter) = 0; }; template @@ -16,10 +17,10 @@ class Delegate { T* object = nullptr; - typedef void(T::*Method)(void*); + typedef void(T::*Method)(TypeParameter); Method method = nullptr; - void Call(void* data) override + void Call(TypeParameter data) override { (object->*method)(data); } @@ -27,10 +28,13 @@ class Delegate struct DelegateDataForFunction : DelegateDataBase { - typedef void(*Func)(void*); + typedef void(*Func)(TypeParameter); Func func = nullptr; - void Call(void* data) override; + void Call(TypeParameter data) override + { + func(data); + } }; DelegateDataBase* firstElement = nullptr; @@ -42,7 +46,7 @@ class Delegate } public: template - void bind(T* object, void(T::*method)(void*)) + void bind(T* object, void(T::*method)(TypeParameter)) { char* str = new char[16]; const char* ptrToObjectRef = reinterpret_cast(&object); @@ -66,20 +70,36 @@ public: mDelegateList.unlock(); } - void bind(void(*func)(void*)); + void bind(void(*func)(TypeParameter)) + { + char* str = new char[8]; + const char* ptrToFuncRef = reinterpret_cast(&func); + for (int i = 0; i < 8; ++i) + str[i] = ptrToFuncRef[i]; + + DelegateDataForFunction* data = new DelegateDataForFunction; + data->next = firstElement; + data->func = func; + data->Hash = FNV1a(str, 8); + delete[] str; + + mDelegateList.lock(); + firstElement = data; + mDelegateList.unlock(); + } template - void unbind(T* object, void(T::*method)(void*)) + void unbind(T* object, void(T::*method)(TypeParameter)) { if (firstElement == nullptr) return; char* str = new char[16]; - const char* ptrToObjectRef = static_cast(&object); + const char* ptrToObjectRef = reinterpret_cast(&object); for (int i = 0; i < 8; ++i) str[i] = ptrToObjectRef[i]; - const char* ptrToMethodRef = static_cast(&method); + const char* ptrToMethodRef = reinterpret_cast(&method); for (int i = 8; i < 16; ++i) str[i] = ptrToMethodRef[i - 8]; @@ -87,27 +107,165 @@ public: DelegateDataBase* iterator = firstElement; DelegateDataBase* temp = nullptr; - while (iterator->next != nullptr) + while (iterator != nullptr) { if (iterator->Hash == Hash) { - mDelegateList.lock(); - if (temp != nullptr) temp->next = iterator->next; - else if (iterator->next == nullptr) - firstElement = nullptr; - - DelegateDataForClass* data = static_cast*>(*iterator); - delete data; - - mDelegateList.unlock(); - return; + else + firstElement = iterator->next; + + delete static_cast*>(iterator); + break; } temp = iterator; + iterator = iterator->next; } } - void Call(void* data) const; + void Call(TypeParameter data) const + { + DelegateDataBase* iterator = firstElement; + while (iterator != nullptr) + { + iterator->Call(data); + iterator = iterator->next; + } + } }; + +template<> +class Delegate +{ + struct DelegateDataBase + { + DelegateDataBase* next = nullptr; + long long Hash = 0; + virtual void Call() = 0; + }; + + template + struct DelegateDataForClass : DelegateDataBase + { + T* object = nullptr; + + typedef void(T::*Method)(); + Method method = nullptr; + + void Call() override + { + (object->*method)(); + } + }; + + struct DelegateDataForFunction : DelegateDataBase + { + typedef void(*Func)(); + Func func = nullptr; + + void Call() override + { + func(); + } + }; + + DelegateDataBase* firstElement = nullptr; + + std::mutex mDelegateList; + + static constexpr unsigned int FNV1a(const char* str, unsigned int n, unsigned int hash = 2166136261U) { + return n == 0 ? hash : FNV1a(str + 1, n - 1, (hash ^ str[0]) * 19777619U); + } +public: + template + void bind(T* object, void(T::*method)()) + { + char* str = new char[16]; + const char* ptrToObjectRef = reinterpret_cast(&object); + for (int i = 0; i < 8; ++i) + str[i] = ptrToObjectRef[i]; + + const char* ptrToMethodRef = reinterpret_cast(&method); + for (int i = 8; i < 16; ++i) + str[i] = ptrToMethodRef[i - 8]; + + DelegateDataForClass* data = new DelegateDataForClass; + data->next = firstElement; + data->object = object; + data->method = method; + data->Hash = FNV1a(str, 16); + + delete[] str; + + mDelegateList.lock(); + firstElement = data; + mDelegateList.unlock(); + } + + void bind(void(*func)()) + { + char* str = new char[8]; + const char* ptrToFuncRef = reinterpret_cast(&func); + for (int i = 0; i < 8; ++i) + str[i] = ptrToFuncRef[i]; + + DelegateDataForFunction* data = new DelegateDataForFunction; + data->next = firstElement; + data->func = func; + data->Hash = FNV1a(str, 8); + delete[] str; + + mDelegateList.lock(); + firstElement = data; + mDelegateList.unlock(); + } + + template + void unbind(T* object, void(T::*method)()) + { + if (firstElement == nullptr) + return; + + char* str = new char[16]; + const char* ptrToObjectRef = reinterpret_cast(&object); + for (int i = 0; i < 8; ++i) + str[i] = ptrToObjectRef[i]; + + const char* ptrToMethodRef = reinterpret_cast(&method); + for (int i = 8; i < 16; ++i) + str[i] = ptrToMethodRef[i - 8]; + + unsigned int Hash = FNV1a(str, 16); + + DelegateDataBase* iterator = firstElement; + DelegateDataBase* temp = nullptr; + while (iterator != nullptr) + { + if (iterator->Hash == Hash) + { + if (temp != nullptr) + temp->next = iterator->next; + else + firstElement = iterator->next; + + delete static_cast*>(iterator); + break; + } + + temp = iterator; + iterator = iterator->next; + } + } + + void Call() const + { + DelegateDataBase* iterator = firstElement; + while (iterator != nullptr) + { + iterator->Call(); + iterator = iterator->next; + } + } +}; \ No newline at end of file diff --git a/exemple/main.cpp b/exemple/main.cpp new file mode 100644 index 0000000..80a63dc --- /dev/null +++ b/exemple/main.cpp @@ -0,0 +1,21 @@ +#include + +#include "Delegate.h" + +class A +{ +public: + void Foo1(int var) { std::cout << "A::Foo1(" << var <<");\n"; } + void Foo2(int var) { std::cout << "A::Foo2(" << var <<");\n"; } +}; + +int main(int argc, char* argv[]) +{ + Delegate delegate; + A a; + delegate.bind(&a, &A::Foo1); + delegate.bind(&a, &A::Foo2); + delegate.unbind(&a, &A::Foo1); + delegate.Call(321); + return 0; +}