Add basic Event class
This commit is contained in:
362
openVulkanoCpp/Base/Event.hpp
Normal file
362
openVulkanoCpp/Base/Event.hpp
Normal file
@@ -0,0 +1,362 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <shared_mutex>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace openVulkanoCpp
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
const EventHandlerType type;
|
||||||
|
protected:
|
||||||
|
EventHandler(EventHandlerType type) : type(type) {}
|
||||||
|
virtual bool ShouldDelete(EventHandler* other) const = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~EventHandler() = default;
|
||||||
|
|
||||||
|
bool ShouldBeDelete(EventHandler* other) const
|
||||||
|
{
|
||||||
|
if (other == this) return true;
|
||||||
|
if (!other || other->type != type) return false;
|
||||||
|
return ShouldDelete(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Notify(Arguments... args) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
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...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Add(EventHandler* handler)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::shared_mutex> lock(mutex);
|
||||||
|
handlers.push_back(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void NotifyAll(Arguments... args) const
|
||||||
|
{
|
||||||
|
std::shared_lock<std::shared_mutex> lock(mutex);
|
||||||
|
for(EventHandler* handler : handlers)
|
||||||
|
{
|
||||||
|
handler->Notify(args...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(Arguments... args)
|
||||||
|
{
|
||||||
|
NotifyAll(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Instance, class Method>
|
||||||
|
void RegisterHandler(Instance* instance, Method method)
|
||||||
|
{
|
||||||
|
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>
|
||||||
|
void operator +=(std::pair<Instance*, Method> instancedMethodPair)
|
||||||
|
{
|
||||||
|
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>
|
||||||
|
void RegisterHandler(std::shared_ptr<Instance> instance, Method method)
|
||||||
|
{
|
||||||
|
Add(new InstancedSharedPtrEventHandler<Instance, Method>(instance, method));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Instance, class Method>
|
||||||
|
void UnregisterHandler(std::shared_ptr<Instance> instance, Method method)
|
||||||
|
{
|
||||||
|
auto handler = InstancedSharedPtrEventHandler<Instance, Method>(instance, method);
|
||||||
|
Remove(&handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Instance, class Method>
|
||||||
|
void operator +=(std::pair<std::shared_ptr<Instance>, Method> instancedMethodPair)
|
||||||
|
{
|
||||||
|
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>
|
||||||
|
void RegisterHandler(std::weak_ptr<Instance> instance, Method method)
|
||||||
|
{
|
||||||
|
Add(new InstancedWeakPtrEventHandler<Instance, Method>(instance, method));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Instance, class Method>
|
||||||
|
void UnregisterHandler(std::weak_ptr<Instance> instance, Method method)
|
||||||
|
{
|
||||||
|
auto handler = InstancedWeakPtrEventHandler<Instance, Method>(instance, method);
|
||||||
|
Remove(&handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Instance, class Method>
|
||||||
|
void RegisterHandlerWeak(std::weak_ptr<Instance> instance, Method method)
|
||||||
|
{
|
||||||
|
Add(new InstancedWeakPtrEventHandler<Instance, Method>(instance, method));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Instance, class Method>
|
||||||
|
void UnregisterHandlerWeak(std::weak_ptr<Instance> instance, Method method)
|
||||||
|
{
|
||||||
|
auto handler = InstancedWeakPtrEventHandler<Instance, Method>(instance, method);
|
||||||
|
Remove(&handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Instance, class Method>
|
||||||
|
void operator +=(std::pair<std::weak_ptr<Instance>, Method> instancedMethodPair)
|
||||||
|
{
|
||||||
|
RegisterHandlerWeak(instancedMethodPair.first, instancedMethodPair.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Instance, class Method>
|
||||||
|
void operator -=(std::pair<std::weak_ptr<Instance>, Method> instancedMethodPair)
|
||||||
|
{
|
||||||
|
RegisterHandlerWeak(instancedMethodPair.first, instancedMethodPair.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterHandler(void (*method)(Arguments...))
|
||||||
|
{
|
||||||
|
handlers.push_back(new StaticEventHandler(method));
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnregisterHandler(void (*method)(Arguments...))
|
||||||
|
{
|
||||||
|
auto handler = StaticEventHandler(method);
|
||||||
|
Remove(&handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator +=(void (*method)(Arguments...))
|
||||||
|
{
|
||||||
|
RegisterHandler(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator -=(void (*method)(Arguments...))
|
||||||
|
{
|
||||||
|
UnregisterHandler(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventHandler* RegisterHandler(Function function)
|
||||||
|
{
|
||||||
|
FunctionalEventHandler* handler = new FunctionalEventHandler(function);
|
||||||
|
Add(handler);
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnregisterHandler(EventHandler* handler)
|
||||||
|
{
|
||||||
|
Remove(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventHandler* operator +=(Function function)
|
||||||
|
{
|
||||||
|
return RegisterHandler(function);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator -=(EventHandler* handler)
|
||||||
|
{
|
||||||
|
Remove(handler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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(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(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(std::weak_ptr<Instance> instance, Method method)
|
||||||
|
{
|
||||||
|
return std::pair<std::weak_ptr<Instance>, Method>(instance, method);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -105,6 +105,7 @@ xcopy /y "$(ProjectDir)Shader\*.spv" "$(OutDir)\Shader\"</Command>
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Base\EngineConstants.hpp" />
|
<ClInclude Include="Base\EngineConstants.hpp" />
|
||||||
|
<ClInclude Include="Base\Event.hpp" />
|
||||||
<ClInclude Include="Base\ICloseable.hpp" />
|
<ClInclude Include="Base\ICloseable.hpp" />
|
||||||
<ClInclude Include="Base\IGraphicsApp.hpp" />
|
<ClInclude Include="Base\IGraphicsApp.hpp" />
|
||||||
<ClInclude Include="Base\IGraphicsAppManager.hpp" />
|
<ClInclude Include="Base\IGraphicsAppManager.hpp" />
|
||||||
|
|||||||
Reference in New Issue
Block a user