Files
OpenVulkano/openVulkanoCpp/Base/Event.hpp

387 lines
10 KiB
C++

#pragma once
#include <functional>
#include <memory>
#include <mutex>
#include <shared_mutex>
#include <vector>
namespace openVulkanoCpp
{
class IEventHandler
{
public:
virtual ~IEventHandler() = default;
virtual void SetInvalid() = 0;
};
template<typename... Arguments>
class Event final
{
public:
typedef std::function<void(Arguments...)> Function;
private:
enum class EventHandlerType { STATIC, INSTANCED, INSTANCED_SHARED_PTR, INSTANCED_WEAK_PTR, FUNCTIONAL };
class EventHandler : public IEventHandler
{
const EventHandlerType type;
bool invalid;
protected:
EventHandler(EventHandlerType type) : type(type), invalid(false) {}
virtual bool ShouldDelete(EventHandler* other) const = 0;
public:
virtual ~EventHandler() = default;
bool ShouldBeDelete(EventHandler* other) const
{
if (other == this) return true;
if (invalid) return true;
if (!other || other->type != type) return false;
return ShouldDelete(other);
}
virtual void Notify(Arguments... args) const = 0;
[[nodiscard]] bool IsInvalid() const { return invalid; }
void SetInvalid() final { invalid = true; }
};
class StaticEventHandler final : public EventHandler
{
public:
typedef void (*Method)(Arguments...);
StaticEventHandler(Method method) : EventHandler(EventHandlerType::STATIC), method(method) {}
void Notify(Arguments... args) const override
{
method(args...);
}
protected:
bool ShouldDelete(EventHandler* other) const override
{
return static_cast<StaticEventHandler*>(other)->method == this->method;
}
private:
Method method;
};
template<class Instance, class Method>
class InstancedEventHandler final : public EventHandler
{
public:
InstancedEventHandler(Instance* instance, Method method) : EventHandler(EventHandlerType::INSTANCED), instance(instance), method(method) {}
void Notify(Arguments... args) const override
{
(instance->*method)(args...);
}
protected:
bool ShouldDelete(EventHandler* other) const override
{
InstancedEventHandler* otherHandler = static_cast<InstancedEventHandler*>(other);
return otherHandler->instance == instance && otherHandler->method == this->method;
}
private:
Instance* instance;
Method method;
};
template<class Instance, class Method>
class InstancedSharedPtrEventHandler final : public EventHandler
{
public:
InstancedSharedPtrEventHandler(std::shared_ptr<Instance> instance, Method method) : EventHandler(EventHandlerType::INSTANCED_SHARED_PTR), instance(instance), method(method) {}
void Notify(Arguments... args) const override
{
(instance.get()->*method)(args...);
}
protected:
bool ShouldDelete(EventHandler* other) const override
{
InstancedSharedPtrEventHandler* otherHandler = static_cast<InstancedSharedPtrEventHandler*>(other);
return otherHandler->instance == instance && otherHandler->method == this->method;
}
private:
std::shared_ptr<Instance> instance;
Method method;
};
template<class Instance, class Method>
class InstancedWeakPtrEventHandler final : public EventHandler
{
public:
InstancedWeakPtrEventHandler(std::weak_ptr<Instance> instance, Method method) : EventHandler(EventHandlerType::INSTANCED_WEAK_PTR), instance(instance), method(method) {}
void Notify(Arguments... args) const override
{
if (auto instancePtr = instance.lock())
{
(instancePtr.get()->*method)(args...);
}
else
{
const_cast<InstancedWeakPtrEventHandler*>(this)->SetInvalid();
}
}
protected:
bool ShouldDelete(EventHandler* other) const override
{
InstancedWeakPtrEventHandler* otherHandler = static_cast<InstancedWeakPtrEventHandler*>(other);
if (otherHandler->method == this->method)
{
if (auto ptr = instance.lock())
{
return ptr == otherHandler->instance.lock();
}
return true;
}
return false;
}
private:
std::weak_ptr<Instance> instance;
Method method;
};
class FunctionalEventHandler final : public EventHandler
{
public:
FunctionalEventHandler(Function function) : EventHandler(EventHandlerType::FUNCTIONAL), function(function) {}
void Notify(Arguments... args) const override
{
function(args...);
}
protected:
bool ShouldDelete(EventHandler* other) const override
{
return false;
}
private:
Function function;
};
std::vector<EventHandler*> handlers;
mutable std::shared_mutex mutex;
void Remove(EventHandler* referenceHandler)
{
std::unique_lock<std::shared_mutex> lock(mutex);
for(size_t i = 0; i < handlers.size(); i++)
{
EventHandler* handler = handlers[i];
if (handler->ShouldBeDelete(referenceHandler))
{
size_t end = handlers.size() - 1;
if (i < end)
{
handlers[i] = handlers[end];
}
delete handler;
handlers.pop_back();
}
}
}
IEventHandler* Add(EventHandler* handler)
{
std::unique_lock<std::shared_mutex> lock(mutex);
handlers.push_back(handler);
return handler;
}
public:
[[nodiscard]] bool HasHandlers() const
{
return !handlers.empty();
}
void NotifyAll(Arguments... args) const
{
std::shared_lock<std::shared_mutex> lock(mutex);
for(EventHandler* handler : handlers)
{
if (!handler->IsInvalid())
handler->Notify(args...);
}
}
void operator()(Arguments&&... args) const
{
NotifyAll(std::forward<Arguments>(args)...);
}
template<class Instance, class Method>
IEventHandler* RegisterHandler(Instance* instance, Method method)
{
return Add(new InstancedEventHandler<Instance, Method>(instance, method));
}
template<class Instance, class Method>
void UnregisterHandler(Instance* instance, Method method)
{
auto handler = InstancedEventHandler<Instance, Method>(instance, method);
Remove(&handler);
}
template<class Instance, class Method>
IEventHandler* operator +=(std::pair<Instance*, Method> instancedMethodPair)
{
return RegisterHandler(instancedMethodPair.first, instancedMethodPair.second);
}
template<class Instance, class Method>
void operator -=(std::pair<Instance*, Method> instancedMethodPair)
{
UnregisterHandler(instancedMethodPair.first, instancedMethodPair.second);
}
template<class Instance, class Method>
IEventHandler* RegisterHandler(const std::shared_ptr<Instance>& instance, Method method)
{
return Add(new InstancedSharedPtrEventHandler<Instance, Method>(instance, method));
}
template<class Instance, class Method>
void UnregisterHandler(const std::shared_ptr<Instance>& instance, Method method)
{
auto handler = InstancedSharedPtrEventHandler<Instance, Method>(instance, method);
Remove(&handler);
}
template<class Instance, class Method>
IEventHandler* operator +=(std::pair<std::shared_ptr<Instance>, Method> instancedMethodPair)
{
return RegisterHandler(instancedMethodPair.first, instancedMethodPair.second);
}
template<class Instance, class Method>
void operator -=(std::pair<std::shared_ptr<Instance>, Method> instancedMethodPair)
{
UnregisterHandler(instancedMethodPair.first, instancedMethodPair.second);
}
template<class Instance, class Method>
IEventHandler* RegisterHandler(const std::weak_ptr<Instance>& instance, Method method)
{
return Add(new InstancedWeakPtrEventHandler<Instance, Method>(instance, method));
}
template<class Instance, class Method>
void UnregisterHandler(const std::weak_ptr<Instance>& instance, Method method)
{
auto handler = InstancedWeakPtrEventHandler<Instance, Method>(instance, method);
Remove(&handler);
}
template<class Instance, class Method>
IEventHandler* RegisterHandlerWeak(const std::weak_ptr<Instance>& instance, Method method)
{
return Add(new InstancedWeakPtrEventHandler<Instance, Method>(instance, method));
}
template<class Instance, class Method>
void UnregisterHandlerWeak(const std::weak_ptr<Instance>& instance, Method method)
{
auto handler = InstancedWeakPtrEventHandler<Instance, Method>(instance, method);
Remove(&handler);
}
template<class Instance, class Method>
IEventHandler* operator +=(std::pair<std::weak_ptr<Instance>, Method> instancedMethodPair)
{
return RegisterHandlerWeak(instancedMethodPair.first, instancedMethodPair.second);
}
template<class Instance, class Method>
void operator -=(std::pair<std::weak_ptr<Instance>, Method> instancedMethodPair)
{
UnregisterHandlerWeak(instancedMethodPair.first, instancedMethodPair.second);
}
IEventHandler* RegisterHandler(void (*method)(Arguments...))
{
return Add(new StaticEventHandler(method));
}
void UnregisterHandler(void (*method)(Arguments...))
{
auto handler = StaticEventHandler(method);
Remove(&handler);
}
IEventHandler* operator +=(void (*method)(Arguments...))
{
return RegisterHandler(method);
}
void operator -=(void (*method)(Arguments...))
{
UnregisterHandler(method);
}
IEventHandler* RegisterHandler(Function function)
{
return Add(new FunctionalEventHandler(function));
}
void UnregisterHandler(EventHandler* handler)
{
Remove(handler);
}
IEventHandler* operator +=(Function function)
{
return RegisterHandler(function);
}
void operator -=(IEventHandler* handler)
{
if (EventHandler* handlerRef = dynamic_cast<EventHandler*>(handler))
{
Remove(handlerRef);
}
}
};
template<class Instance, class Method>
constexpr std::pair<Instance*, Method> EventHandler(Instance* instance, Method method)
{
return std::pair<Instance*, Method>(instance, method);
}
template<class Instance, class Method>
constexpr std::pair<std::shared_ptr<Instance>, Method> EventHandler(const std::shared_ptr<Instance>& instance, Method method)
{
return std::pair<std::shared_ptr<Instance>, Method>(instance, method);
}
template<class Instance, class Method>
constexpr std::pair<std::weak_ptr<Instance>, Method> EventHandler(const std::weak_ptr<Instance>& instance, Method method)
{
return std::pair<std::weak_ptr<Instance>, Method>(instance, method);
}
template<class Instance, class Method>
constexpr std::pair<std::weak_ptr<Instance>, Method> EventHandlerWeak(const std::weak_ptr<Instance>& instance, Method method)
{
return std::pair<std::weak_ptr<Instance>, Method>(instance, method);
}
}