Make event listeners threaded.
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
Signed-off-by: Deukhoofd <Deukhoofd@gmail.com>
This commit is contained in:
parent
665227a033
commit
208bb097dd
|
@ -14,6 +14,9 @@ option(STATICC "Whether gcc and stdc++ should be linked statically to the librar
|
||||||
include(CmakeConanSetup.cmake)
|
include(CmakeConanSetup.cmake)
|
||||||
SetupConan()
|
SetupConan()
|
||||||
|
|
||||||
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
# Set whether we want a static or shared library.
|
# Set whether we want a static or shared library.
|
||||||
set(LIBTYPE STATIC)
|
set(LIBTYPE STATIC)
|
||||||
if (SHARED)
|
if (SHARED)
|
||||||
|
@ -44,7 +47,7 @@ if (STATICC)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# And link the libraries together
|
# And link the libraries together
|
||||||
target_link_libraries(CreatureLib PUBLIC ${_LIBRARYLINKS})
|
target_link_libraries(CreatureLib PUBLIC ${_LIBRARYLINKS} Threads::Threads)
|
||||||
|
|
||||||
if (TESTS)
|
if (TESTS)
|
||||||
# Create Test executable
|
# Create Test executable
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define CREATURELIB_EVENTHOOK_HPP
|
#define CREATURELIB_EVENTHOOK_HPP
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../../Library/Exceptions/CreatureException.hpp"
|
#include "../../Library/Exceptions/CreatureException.hpp"
|
||||||
#include "EventData.hpp"
|
#include "EventData.hpp"
|
||||||
|
@ -18,6 +19,7 @@ namespace CreatureLib::Battling {
|
||||||
size_t _offset;
|
size_t _offset;
|
||||||
size_t _capacity;
|
size_t _capacity;
|
||||||
uint8_t* _memory = nullptr;
|
uint8_t* _memory = nullptr;
|
||||||
|
std::thread* _currentThread = nullptr;
|
||||||
|
|
||||||
static constexpr size_t initialSize = 2048;
|
static constexpr size_t initialSize = 2048;
|
||||||
static constexpr size_t stepSize = 1024;
|
static constexpr size_t stepSize = 1024;
|
||||||
|
@ -33,7 +35,14 @@ namespace CreatureLib::Battling {
|
||||||
EventHook(const EventHook&) = delete;
|
EventHook(const EventHook&) = delete;
|
||||||
EventHook& operator=(const EventHook&) = delete;
|
EventHook& operator=(const EventHook&) = delete;
|
||||||
|
|
||||||
~EventHook() { free(_memory); }
|
~EventHook() {
|
||||||
|
free(_memory);
|
||||||
|
if (_currentThread != nullptr && _currentThread->joinable()) {
|
||||||
|
_currentThread->join();
|
||||||
|
delete _currentThread;
|
||||||
|
_currentThread = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
size_t GetPosition() const noexcept { return _offset; }
|
size_t GetPosition() const noexcept { return _offset; }
|
||||||
size_t GetCapacity() const noexcept { return _capacity; }
|
size_t GetCapacity() const noexcept { return _capacity; }
|
||||||
|
@ -41,6 +50,11 @@ namespace CreatureLib::Battling {
|
||||||
template <class T, class... parameters> void Trigger(parameters... args) {
|
template <class T, class... parameters> void Trigger(parameters... args) {
|
||||||
if (_listeners.size() == 0)
|
if (_listeners.size() == 0)
|
||||||
return;
|
return;
|
||||||
|
if (_currentThread != nullptr && _currentThread->joinable()) {
|
||||||
|
_currentThread->join();
|
||||||
|
delete _currentThread;
|
||||||
|
_currentThread = nullptr;
|
||||||
|
}
|
||||||
if (_offset + sizeof(T) >= _capacity) {
|
if (_offset + sizeof(T) >= _capacity) {
|
||||||
_capacity += stepSize;
|
_capacity += stepSize;
|
||||||
auto newPtr = realloc(_memory, _capacity);
|
auto newPtr = realloc(_memory, _capacity);
|
||||||
|
@ -52,12 +66,25 @@ namespace CreatureLib::Battling {
|
||||||
uint8_t* ptr = _memory + _offset;
|
uint8_t* ptr = _memory + _offset;
|
||||||
T* event = new (ptr) T(args...);
|
T* event = new (ptr) T(args...);
|
||||||
_offset += sizeof(T);
|
_offset += sizeof(T);
|
||||||
|
_currentThread = new std::thread(&EventHook::RunListeners, this, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterListener(const EventHookFunc& func) { _listeners.push_back(func); }
|
||||||
|
|
||||||
|
void FinishListening() {
|
||||||
|
if (_currentThread != nullptr && _currentThread->joinable()) {
|
||||||
|
_currentThread->join();
|
||||||
|
delete _currentThread;
|
||||||
|
_currentThread = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void RunListeners(EventData* event) {
|
||||||
for (auto listener : _listeners) {
|
for (auto listener : _listeners) {
|
||||||
try_creature(listener(event), "Exception in event listener");
|
try_creature(listener(event), "Exception in event listener");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterListener(const EventHookFunc& func) { _listeners.push_back(func); }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif // CREATURELIB_EVENTHOOK_HPP
|
#endif // CREATURELIB_EVENTHOOK_HPP
|
||||||
|
|
|
@ -89,6 +89,7 @@ void Battle::CheckChoicesSetAndRun() {
|
||||||
this->_currentTurnQueue = nullptr;
|
this->_currentTurnQueue = nullptr;
|
||||||
}
|
}
|
||||||
TriggerEventListener<TurnEndEvent>();
|
TriggerEventListener<TurnEndEvent>();
|
||||||
|
_eventHook.FinishListening();
|
||||||
}
|
}
|
||||||
|
|
||||||
ArbUt::BorrowedPtr<ChoiceQueue> Battle::GetCurrentTurnQueue() const noexcept { return _currentTurnQueue; }
|
ArbUt::BorrowedPtr<ChoiceQueue> Battle::GetCurrentTurnQueue() const noexcept { return _currentTurnQueue; }
|
||||||
|
|
|
@ -13,6 +13,7 @@ TEST_CASE("Build and use event hook", "[Battling]") {
|
||||||
for (size_t i = 0; i < 10; i++) {
|
for (size_t i = 0; i < 10; i++) {
|
||||||
eventHook.Trigger<DamageEvent>(nullptr, DamageSource::AttackDamage, 0, 0);
|
eventHook.Trigger<DamageEvent>(nullptr, DamageSource::AttackDamage, 0, 0);
|
||||||
}
|
}
|
||||||
|
eventHook.FinishListening();
|
||||||
REQUIRE(events.size() == 10);
|
REQUIRE(events.size() == 10);
|
||||||
REQUIRE(events[0]->GetKind() == EventDataKind::Damage);
|
REQUIRE(events[0]->GetKind() == EventDataKind::Damage);
|
||||||
}
|
}
|
||||||
|
@ -24,6 +25,7 @@ TEST_CASE("Build and use event hook a lot", "[Battling]") {
|
||||||
for (size_t i = 0; i < 10000; i++) {
|
for (size_t i = 0; i < 10000; i++) {
|
||||||
eventHook.Trigger<DamageEvent>(nullptr, DamageSource::AttackDamage, 0, 0);
|
eventHook.Trigger<DamageEvent>(nullptr, DamageSource::AttackDamage, 0, 0);
|
||||||
}
|
}
|
||||||
|
eventHook.FinishListening();
|
||||||
REQUIRE(events.size() == 10000);
|
REQUIRE(events.size() == 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue