From 59f147fafc107fb1b5de54a74a9aa8ded367d814 Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Fri, 5 Jun 2026 21:07:58 +0700 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=B1=D0=B8=D0=B1=D0=BB=D0=B8=D0=BE=D1=82=D0=B5=D0=BA=D1=83=20?= =?UTF-8?q?Delegate.h=20=D0=B4=D0=BE=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5?= =?UTF-8?q?=D0=B4=D0=BD=D0=B5=D0=B9=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/Delegate/Delegate.h | 450 +++++++++++++-------------------------- 1 file changed, 151 insertions(+), 299 deletions(-) diff --git a/Core/Delegate/Delegate.h b/Core/Delegate/Delegate.h index 1548fb8..5c7f626 100644 --- a/Core/Delegate/Delegate.h +++ b/Core/Delegate/Delegate.h @@ -1,333 +1,185 @@ -#pragma once +// Create by Jiga228 (https://git.burntroosters.twc1.net/Jiga228) +#pragma once + +#include #include +#include -template +/* + * Этоот класс по своей сути односвязный список, + * каждый элемент которого - подписавшийся объект. + * Реализация для случая когда Type_Parameter != void + */ + +template class Delegate { - struct DelegateDataBase + class ObjectWasDelete : public std::runtime_error { - virtual ~DelegateDataBase() = default; - DelegateDataBase* next = nullptr; - long long Hash = 0; - virtual void Call(TypeParameter) = 0; + public: + ObjectWasDelete() : std::runtime_error("Delegate (call): Object was delete") {} }; - - template - struct DelegateDataForClass : DelegateDataBase + + /* + * Базовая структура для записи подптсок + */ + struct BaseListData { - T* object = nullptr; + std::shared_ptr next; + virtual ~BaseListData() = default; + virtual void call(Type_Parameter data) = 0; + }; - typedef void(T::*Method)(TypeParameter); + template + struct ObjectListData : public BaseListData + { + using Method = void(Type_Object::*)(Type_Parameter); + std::weak_ptr object; Method method = nullptr; - - void Call(TypeParameter data) override + + ObjectListData() = default; + ObjectListData(std::weak_ptr object, Method method) : object(std::move(object)), method(method) {} + void call(Type_Parameter data) { - (object->*method)(data); - } - }; - - struct DelegateDataForFunction : DelegateDataBase - { - typedef void(*Func)(TypeParameter); - Func func = nullptr; - - void Call(TypeParameter data) override - { - func(data); + if (auto shared_object = object.lock()) + { + (shared_object.get()->*method)(data); + } + else + { + throw ObjectWasDelete(); + } } }; - 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); - } + struct FunctionListData : public BaseListData + { + void(*function)(Type_Parameter); + FunctionListData() = default; + FunctionListData(void(*func)(Type_Parameter)) : function(func) {} + void call(Type_Parameter data) + { + function(data); + } + }; + + std::shared_ptr list_head = nullptr; + std::mutex m_list; public: - template - void bind(T* object, void(T::*method)(TypeParameter)) + template + void bind(std::weak_ptr object, void (Type_Object::*method)(Type_Parameter)) { - char* str = new char[sizeof(T*) + sizeof(void(T::*)(TypeParameter))]; - const char* ptrToObjectRef = reinterpret_cast(&object); - for (long unsigned int i = 0; i < sizeof(T*); ++i) - str[i] = ptrToObjectRef[i]; - - const char* ptrToMethodRef = reinterpret_cast(&method); - for (long unsigned int i = sizeof(T*); i < sizeof(T*) + sizeof(void(T::*)(TypeParameter)); ++i) - str[i] = ptrToMethodRef[i - sizeof(T*)]; - - DelegateDataForClass* data = new DelegateDataForClass; - data->next = firstElement; - data->object = object; - data->method = method; - data->Hash = FNV1a(str, sizeof(T*) + sizeof(void(T::*)(TypeParameter))); - - delete[] str; - - mDelegateList.lock(); - firstElement = data; - mDelegateList.unlock(); + if (!object.expired() && !method) + return; + + std::lock_guard lock(m_list); + std::shared_ptr old_head = list_head; + list_head = std::make_shared>(object, method); + list_head->next = old_head; } - - void bind(void(*func)(TypeParameter)) - { - char* str = new char[sizeof(void(*)(TypeParameter))]; - const char* ptrToFuncRef = reinterpret_cast(&func); - for (int i = 0; i < sizeof(void(*)(TypeParameter)); ++i) - str[i] = ptrToFuncRef[i]; - DelegateDataForFunction* data = new DelegateDataForFunction; - data->next = firstElement; - data->func = func; - data->Hash = FNV1a(str, sizeof(func)); - delete[] str; - - mDelegateList.lock(); - firstElement = data; - mDelegateList.unlock(); - } - - template - void unbind(T* object, void(T::*method)(TypeParameter)) + void bind(void(*function)(Type_Parameter)) { - if (firstElement == nullptr) - return; - - char* str = new char[sizeof(T*) + sizeof(void(T::*)(TypeParameter))]; - const char* ptrToObjectRef = reinterpret_cast(&object); - for (long unsigned int i = 0; i < 8; ++i) - str[i] = ptrToObjectRef[i]; - - const char* ptrToMethodRef = reinterpret_cast(&method); - for (long unsigned int i = sizeof(T*); i < sizeof(T*) + sizeof(void(T::*)(TypeParameter)); ++i) - str[i] = ptrToMethodRef[i - sizeof(T*)]; - - unsigned int Hash = FNV1a(str, sizeof(T*) + sizeof(void(T::*)(TypeParameter))); - - DelegateDataBase* iterator = firstElement; - DelegateDataBase* temp = nullptr; - while (iterator != nullptr) + if (!function) + return; + + std::lock_guard lock(m_list); + std::shared_ptr old_head = list_head; + list_head = std::make_shared(function); + list_head->next = old_head; + } + + template + void unbind(std::shared_ptr object, void(Type_Object::*method)(Type_Parameter)) + { + std::lock_guard lock(m_list); + + if (!list_head) + return; + + if (auto object_list_data = dynamic_cast*>(list_head.get())) { - if (iterator->Hash == Hash) + std::shared_ptr shared_object_list_data = object_list_data->object.lock(); + if (!shared_object_list_data) + { + list_head = list_head->next; + } + else if (shared_object_list_data == object && object_list_data->method == method) { - if (temp != nullptr) - temp->next = iterator->next; - else - firstElement = iterator->next; - - delete static_cast*>(iterator); - break; + list_head = list_head->next; + return; } - - temp = iterator; - iterator = iterator->next; } + + std::shared_ptr old_it = list_head, iterator = list_head->next; + while (iterator) + { + if (auto object_list = dynamic_cast*>(iterator.get())) + { + if (object_list->object.expired()) + old_it->next = iterator->next; + if (object_list->object.lock() == object && object_list->method == method) + { + old_it->next = iterator->next; + return; + } + } + old_it = iterator; + iterator = iterator->next; + } } - - void unbind(void(*func)(TypeParameter)) + + void unbind(void(*func)(Type_Parameter)) { - char* str = new char[sizeof(void(*)(TypeParameter))]; - const char* ptrToFuncRef = reinterpret_cast(&func); - for (int i = 0; i < sizeof(void(*)(TypeParameter)); ++i) - str[i] = ptrToFuncRef[i]; - - unsigned int Hash = FNV1a(str, sizeof(void(*)(TypeParameter))); - delete[] str; - - DelegateDataBase* iterator = firstElement; - DelegateDataBase* temp = nullptr; - while (iterator != nullptr) + std::lock_guard lock(m_list); + + if (!list_head) + return; + + if (auto function_list_data = dynamic_cast(list_head.get())) { - if (iterator->Hash == Hash) + if (function_list_data->function == func) { - if (temp != nullptr) - temp->next = iterator->next; - else - firstElement = iterator->next; - - delete static_cast(iterator); - break; + list_head = list_head->next; + return; } - - temp = iterator; - iterator = iterator->next; } + + std::shared_ptr old_it = list_head, iterator = list_head->next; + while (iterator) + { + if (auto function_list = dynamic_cast(iterator.get())) + { + if (function_list->function == func) + { + old_it->next = iterator->next; + return; + } + } + iterator = iterator->next; + } } - - void Call(TypeParameter data) const - { - DelegateDataBase* iterator = firstElement; - while (iterator != nullptr) - { - iterator->Call(data); - iterator = iterator->next; - } - } -}; - -template<> -class Delegate -{ - struct DelegateDataBase - { - virtual ~DelegateDataBase() = default; - 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)()) + void call(Type_Parameter data) { - char* str = new char[sizeof(T*) + sizeof(void(T::*)())]; - const char* ptrToObjectRef = reinterpret_cast(&object); - for (int i = 0; i < sizeof(T*); ++i) - str[i] = ptrToObjectRef[i]; - - const char* ptrToMethodRef = reinterpret_cast(&method); - for (int i = sizeof(T*); i < sizeof(T*) + sizeof(void(T::*)()); ++i) - str[i] = ptrToMethodRef[i - sizeof(T*)]; - - DelegateDataForClass* data = new DelegateDataForClass; - data->next = firstElement; - data->object = object; - data->method = method; - data->Hash = FNV1a(str, sizeof(T*) + sizeof(void(T::*)())); - - delete[] str; - - mDelegateList.lock(); - firstElement = data; - mDelegateList.unlock(); - } - - void bind(void(*func)()) - { - char* str = new char[sizeof(func)]; - const char* ptrToFuncRef = reinterpret_cast(&func); - for (int i = 0; i < sizeof(void(*)()); ++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[sizeof(T*) + sizeof(void(T::*)())]; - const char* ptrToObjectRef = reinterpret_cast(&object); - for (int i = 0; i < sizeof(T*); ++i) - str[i] = ptrToObjectRef[i]; - - const char* ptrToMethodRef = reinterpret_cast(&method); - for (int i = sizeof(T*); i < sizeof(T*) + sizeof(void(T::*)()); ++i) - str[i] = ptrToMethodRef[i - sizeof(T*)]; - - unsigned int Hash = FNV1a(str, sizeof(T*) + sizeof(void(T::*)())); - - 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 unbind(void(*func)()) - { - char* str = new char[sizeof(void(*)())]; - const char* ptrToFuncRef = reinterpret_cast(&func); - for (int i = 0; i < sizeof(void(*)()); ++i) - str[i] = ptrToFuncRef[i]; - - unsigned int Hash = FNV1a(str, sizeof(void(*)())); - delete[] str; - - 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; - } + std::lock_guard lock(m_list); + std::shared_ptr old_head, iterator = list_head; + while(iterator) + { + try { + iterator->call(data); + } catch (const ObjectWasDelete&) { + if (iterator == list_head) + { + list_head = list_head->next; + } + else + { + old_head->next = iterator->next; + } + } + iterator = iterator->next; + } } }; \ No newline at end of file