Fix Undefine behevior

This commit is contained in:
Jiga228
2026-06-05 21:05:39 +07:00
parent 2c68a258d2
commit 56c93d5b1b
+264 -236
View File
@@ -1,332 +1,360 @@
#pragma once #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);
for (long unsigned int i = 0; i < sizeof(T*); ++i)
str[i] = ptrToObjectRef[i];
const char* ptrToMethodRef = reinterpret_cast<const char*>(&method);
for (long unsigned int i = sizeof(T*); i < sizeof(T*) + sizeof(void(T::*)(TypeParameter)); ++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::*)(TypeParameter)));
delete[] str;
mDelegateList.lock();
firstElement = data;
mDelegateList.unlock();
}
void bind(void(*func)(TypeParameter))
{
char* str = new char[sizeof(void(*)(TypeParameter))];
const char* ptrToFuncRef = reinterpret_cast<const char*>(&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<typename T>
void unbind(T* object, void(T::*method)(TypeParameter))
{
if (firstElement == nullptr)
return; return;
char* str = new char[sizeof(T*) + sizeof(void(T::*)(TypeParameter))]; std::lock_guard<std::mutex> lock(m_list);
const char* ptrToObjectRef = reinterpret_cast<const char*>(&object); std::shared_ptr<BaseListData> old_head = list_head;
for (long unsigned int i = 0; i < 8; ++i) list_head = std::make_shared<ObjectListData<Type_Object>>(object, method);
str[i] = ptrToObjectRef[i]; list_head->next = old_head;
const char* ptrToMethodRef = reinterpret_cast<const char*>(&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 (iterator->Hash == Hash)
{
if (temp != nullptr)
temp->next = iterator->next;
else
firstElement = iterator->next;
delete static_cast<DelegateDataForClass<T>*>(iterator);
break;
} }
temp = iterator; void bind(void(*function)(Type_Parameter))
{
if (!function)
return;
std::lock_guard<std::mutex> lock(m_list);
std::shared_ptr<BaseListData> old_head = list_head;
list_head = std::make_shared<FunctionListData>(function);
list_head->next = old_head;
}
template<class Type_Object>
void unbind(std::shared_ptr<Type_Object> object, void(Type_Object::*method)(Type_Parameter))
{
std::lock_guard<std::mutex> lock(m_list);
if (!list_head)
return;
if (auto object_list_data = dynamic_cast<ObjectListData<Type_Object>*>(list_head.get()))
{
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)
{
list_head = list_head->next;
return;
}
}
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; 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; 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; 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); 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; iterator = iterator->next;
} }
} }
}; };
#pragma once
/*
* Реализация для случая когда Type_Parameter == void
*/
template<> template<>
class Delegate<void> class Delegate<void>
{ {
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; };
/*
* Базовая структура для записи подптсок
*/
struct BaseListData
{
std::shared_ptr<BaseListData> next;
virtual ~BaseListData() = default;
virtual void call() = 0; virtual void call() = 0;
}; };
template<class T> template<class Type_Object>
struct DelegateDataForClass : DelegateDataBase struct ObjectListData : public BaseListData
{ {
T* object = nullptr; using Method = void(Type_Object::*)();
std::weak_ptr<Type_Object> object;
typedef void(T::*Method)();
Method method = nullptr; Method method = nullptr;
void call() override ObjectListData() = default;
ObjectListData(std::weak_ptr<Type_Object> object, Method method) : object(std::move(object)), method(method) {}
void call()
{ {
(object->*method)(); if (auto shared_object = object.lock())
{
(shared_object.get()->*method)();
}
else
{
throw ObjectWasDelete();
}
} }
}; };
struct DelegateDataForFunction : DelegateDataBase struct FunctionListData : public BaseListData
{ {
typedef void(*Func)(); void(*function)();
Func func = nullptr; FunctionListData() = default;
FunctionListData(void(*func)()) : function(func) {}
void call() override void call()
{ {
func(); function();
} }
}; };
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)()) void bind(std::weak_ptr<Type_Object> object, void (Type_Object::*method)())
{ {
char* str = new char[sizeof(T*) + sizeof(void(T::*)())]; if (!object.expired() && !method)
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; return;
char* str = new char[sizeof(T*) + sizeof(void(T::*)())]; std::lock_guard<std::mutex> lock(m_list);
const char* ptrToObjectRef = reinterpret_cast<const char*>(&object); std::shared_ptr<BaseListData> old_head = list_head;
for (int i = 0; i < sizeof(T*); ++i) list_head = std::make_shared<ObjectListData<Type_Object>>(object, method);
str[i] = ptrToObjectRef[i]; list_head->next = old_head;
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; void bind(void(*function)())
{
if (!function)
return;
std::lock_guard<std::mutex> lock(m_list);
std::shared_ptr<BaseListData> old_head = list_head;
list_head = std::make_shared<FunctionListData>(function);
list_head->next = old_head;
}
template<class Type_Object>
void unbind(std::shared_ptr<Type_Object> object, void(Type_Object::*method)())
{
std::lock_guard<std::mutex> lock(m_list);
if (!list_head)
return;
if (auto object_list_data = dynamic_cast<ObjectListData<Type_Object>*>(list_head.get()))
{
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)
{
list_head = list_head->next;
return;
}
}
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; iterator = iterator->next;
} }
} }
void unbind(void(*func)()) void unbind(void(*func)())
{ {
char* str = new char[sizeof(void(*)())]; std::lock_guard<std::mutex> lock(m_list);
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(*)())); 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; 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; iterator = iterator->next;
} }
} }
void Call() const void call()
{ {
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)
{ {
try {
iterator->call(); iterator->call();
} catch (const ObjectWasDelete&) {
if (iterator == list_head)
{
list_head = list_head->next;
}
else
{
old_head->next = iterator->next;
}
}
iterator = iterator->next; iterator = iterator->next;
} }
} }