Fix Undefine behevior
This commit is contained in:
+264
-236
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user