Обновил библиотеку Delegate.h до последней версии

This commit is contained in:
Jiga228
2026-06-05 21:07:58 +07:00
parent cf4f8236f6
commit 59f147fafc
+134 -282
View File
@@ -1,333 +1,185 @@
#pragma once // Create by Jiga228 (https://git.burntroosters.twc1.net/Jiga228)
#pragma once
#include <memory>
#include <mutex> #include <mutex>
#include <stdexcept>
template<typename TypeParameter> /*
* Этоот класс по своей сути односвязный список,
* каждый элемент которого - подписавшийся объект.
* Реализация для случая когда Type_Parameter != void
*/
template<typename Type_Parameter>
class Delegate class Delegate
{ {
struct DelegateDataBase class ObjectWasDelete : public std::runtime_error
{ {
virtual ~DelegateDataBase() = default; public:
DelegateDataBase* next = nullptr; ObjectWasDelete() : std::runtime_error("Delegate (call): Object was delete") {}
long long Hash = 0;
virtual void Call(TypeParameter) = 0;
}; };
template<class T> /*
struct DelegateDataForClass : DelegateDataBase * Базовая структура для записи подптсок
*/
struct BaseListData
{ {
T* object = nullptr; std::shared_ptr<BaseListData> next;
virtual ~BaseListData() = default;
virtual void call(Type_Parameter data) = 0;
};
typedef void(T::*Method)(TypeParameter); template<class Type_Object>
struct ObjectListData : public BaseListData
{
using Method = void(Type_Object::*)(Type_Parameter);
std::weak_ptr<Type_Object> object;
Method method = nullptr; Method method = nullptr;
void Call(TypeParameter data) override ObjectListData() = default;
ObjectListData(std::weak_ptr<Type_Object> object, Method method) : object(std::move(object)), method(method) {}
void call(Type_Parameter data)
{ {
(object->*method)(data); if (auto shared_object = object.lock())
{
(shared_object.get()->*method)(data);
}
else
{
throw ObjectWasDelete();
}
} }
}; };
struct DelegateDataForFunction : DelegateDataBase struct FunctionListData : public BaseListData
{ {
typedef void(*Func)(TypeParameter); void(*function)(Type_Parameter);
Func func = nullptr; FunctionListData() = default;
FunctionListData(void(*func)(Type_Parameter)) : function(func) {}
void Call(TypeParameter data) override void call(Type_Parameter data)
{ {
func(data); function(data);
} }
}; };
DelegateDataBase* firstElement = nullptr; std::shared_ptr<BaseListData> list_head = nullptr;
std::mutex m_list;
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: public:
template<typename T> template<class Type_Object>
void bind(T* object, void(T::*method)(TypeParameter)) void bind(std::weak_ptr<Type_Object> object, void (Type_Object::*method)(Type_Parameter))
{ {
char* str = new char[sizeof(T*) + sizeof(void(T::*)(TypeParameter))]; if (!object.expired() && !method)
const char* ptrToObjectRef = reinterpret_cast<const char*>(&object); return;
for (long unsigned int i = 0; i < sizeof(T*); ++i)
str[i] = ptrToObjectRef[i];
const char* ptrToMethodRef = reinterpret_cast<const char*>(&method); std::lock_guard<std::mutex> lock(m_list);
for (long unsigned int i = sizeof(T*); i < sizeof(T*) + sizeof(void(T::*)(TypeParameter)); ++i) std::shared_ptr<BaseListData> old_head = list_head;
str[i] = ptrToMethodRef[i - sizeof(T*)]; list_head = std::make_shared<ObjectListData<Type_Object>>(object, method);
list_head->next = old_head;
DelegateDataForClass<T>* data = new DelegateDataForClass<T>;
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();
} }
void bind(void(*func)(TypeParameter)) void bind(void(*function)(Type_Parameter))
{ {
char* str = new char[sizeof(void(*)(TypeParameter))]; if (!function)
const char* ptrToFuncRef = reinterpret_cast<const char*>(&func); return;
for (int i = 0; i < sizeof(void(*)(TypeParameter)); ++i)
str[i] = ptrToFuncRef[i];
DelegateDataForFunction* data = new DelegateDataForFunction; std::lock_guard<std::mutex> lock(m_list);
data->next = firstElement; std::shared_ptr<BaseListData> old_head = list_head;
data->func = func; list_head = std::make_shared<FunctionListData>(function);
data->Hash = FNV1a(str, sizeof(func)); list_head->next = old_head;
delete[] str;
mDelegateList.lock();
firstElement = data;
mDelegateList.unlock();
} }
template<typename T> template<class Type_Object>
void unbind(T* object, void(T::*method)(TypeParameter)) void unbind(std::shared_ptr<Type_Object> object, void(Type_Object::*method)(Type_Parameter))
{ {
if (firstElement == nullptr) std::lock_guard<std::mutex> lock(m_list);
return;
char* str = new char[sizeof(T*) + sizeof(void(T::*)(TypeParameter))]; if (!list_head)
const char* ptrToObjectRef = reinterpret_cast<const char*>(&object); return;
for (long unsigned int i = 0; i < 8; ++i)
str[i] = ptrToObjectRef[i];
const char* ptrToMethodRef = reinterpret_cast<const char*>(&method); if (auto object_list_data = dynamic_cast<ObjectListData<Type_Object>*>(list_head.get()))
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 (iterator->Hash == Hash) std::shared_ptr<Type_Object> 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) list_head = list_head->next;
temp->next = iterator->next; return;
else
firstElement = iterator->next;
delete static_cast<DelegateDataForClass<T>*>(iterator);
break;
} }
temp = iterator;
iterator = iterator->next;
} }
std::shared_ptr<BaseListData> old_it = list_head, iterator = list_head->next;
while (iterator)
{
if (auto object_list = dynamic_cast<ObjectListData<Type_Object>*>(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))]; std::lock_guard<std::mutex> lock(m_list);
const char* ptrToFuncRef = reinterpret_cast<const char*>(&func);
for (int i = 0; i < sizeof(void(*)(TypeParameter)); ++i)
str[i] = ptrToFuncRef[i];
unsigned int Hash = FNV1a(str, sizeof(void(*)(TypeParameter))); if (!list_head)
delete[] str; return;
DelegateDataBase* iterator = firstElement; if (auto function_list_data = dynamic_cast<FunctionListData*>(list_head.get()))
DelegateDataBase* temp = nullptr;
while (iterator != nullptr)
{ {
if (iterator->Hash == Hash) if (function_list_data->function == func)
{ {
if (temp != nullptr) list_head = list_head->next;
temp->next = iterator->next; return;
else
firstElement = iterator->next;
delete static_cast<DelegateDataForFunction*>(iterator);
break;
} }
temp = iterator;
iterator = iterator->next;
} }
std::shared_ptr<BaseListData> old_it = list_head, iterator = list_head->next;
while (iterator)
{
if (auto function_list = dynamic_cast<FunctionListData*>(iterator.get()))
{
if (function_list->function == func)
{
old_it->next = iterator->next;
return;
}
}
iterator = iterator->next;
}
} }
void Call(TypeParameter data) const void call(Type_Parameter data)
{ {
DelegateDataBase* iterator = firstElement; std::lock_guard<std::mutex> lock(m_list);
while (iterator != nullptr) std::shared_ptr<BaseListData> old_head, iterator = list_head;
{ while(iterator)
iterator->Call(data); {
iterator = iterator->next; try {
} iterator->call(data);
} } catch (const ObjectWasDelete&) {
}; if (iterator == list_head)
{
template<> list_head = list_head->next;
class Delegate<void> }
{ else
struct DelegateDataBase {
{ old_head->next = iterator->next;
virtual ~DelegateDataBase() = default; }
DelegateDataBase* next = nullptr; }
long long Hash = 0; iterator = iterator->next;
virtual void call() = 0; }
};
template<class T>
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<typename T>
void bind(T* object, void(T::*method)())
{
char* str = new char[sizeof(T*) + sizeof(void(T::*)())];
const char* ptrToObjectRef = reinterpret_cast<const char*>(&object);
for (int i = 0; i < sizeof(T*); ++i)
str[i] = ptrToObjectRef[i];
const char* ptrToMethodRef = reinterpret_cast<const char*>(&method);
for (int i = sizeof(T*); i < sizeof(T*) + sizeof(void(T::*)()); ++i)
str[i] = ptrToMethodRef[i - sizeof(T*)];
DelegateDataForClass<T>* data = new DelegateDataForClass<T>;
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<const char*>(&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<typename T>
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<const char*>(&object);
for (int i = 0; i < sizeof(T*); ++i)
str[i] = ptrToObjectRef[i];
const char* ptrToMethodRef = reinterpret_cast<const char*>(&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<DelegateDataForClass<T>*>(iterator);
break;
}
temp = iterator;
iterator = iterator->next;
}
}
void unbind(void(*func)())
{
char* str = new char[sizeof(void(*)())];
const char* ptrToFuncRef = reinterpret_cast<const char*>(&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<DelegateDataForFunction*>(iterator);
break;
}
temp = iterator;
iterator = iterator->next;
}
}
void Call() const
{
DelegateDataBase* iterator = firstElement;
while (iterator != nullptr)
{
iterator->call();
iterator = iterator->next;
}
} }
}; };