diff --git a/Delegate/Delegate.cpp b/Delegate/Delegate.cpp new file mode 100644 index 0000000..5066edf --- /dev/null +++ b/Delegate/Delegate.cpp @@ -0,0 +1,34 @@ +#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 new file mode 100644 index 0000000..d56a74a --- /dev/null +++ b/Delegate/Delegate.h @@ -0,0 +1,113 @@ +#pragma once + +#include + +class Delegate +{ + struct DelegateDataBase + { + DelegateDataBase* next = nullptr; + long long Hash = 0; + virtual void Call(void*) = 0; + }; + + template + struct DelegateDataForClass : DelegateDataBase + { + T* object = nullptr; + + typedef void(T::*Method)(void*); + Method method = nullptr; + + void Call(void* data) override + { + (object->*method)(data); + } + }; + + struct DelegateDataForFunction : DelegateDataBase + { + typedef void(*Func)(void*); + Func func = nullptr; + + void Call(void* data) override; + }; + + 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*)) + { + 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)(void*)); + + template + void unbind(T* object, void(T::*method)(void*)) + { + if (firstElement == nullptr) + return; + + char* str = new char[16]; + const char* ptrToObjectRef = static_cast(&object); + for (int i = 0; i < 8; ++i) + str[i] = ptrToObjectRef[i]; + + const char* ptrToMethodRef = static_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->next != 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; + } + + temp = iterator; + } + } + + void Call(void* data) const; +}; diff --git a/README.md b/README.md index 9296ffc..1fa7d69 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ -# Delegate \ No newline at end of file +# Delegate +That library implement delegate for C++. \ No newline at end of file