From ed8c362f23d44571da18b33eb9274c61df9a9d64 Mon Sep 17 00:00:00 2001 From: Articha Date: Fri, 5 Jan 2024 16:13:36 +0300 Subject: [PATCH] Now events with higher traits can trigger lower traits. Added corresponding test Example: Event with traits 201, 202 can now trigger receivers with registration on: 1. 201, 202 2. 201 3. 202 --- CMakeLists.txt | 1 + src/events/event.cpp | 42 ++++++++++++++++++------ src/events/event.hpp | 1 + tests/events/different_events.cpp | 54 +++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 tests/events/different_events.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 302ae13..4272e10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,6 +89,7 @@ set(t_data set(t_events ${tests}/events/event.cpp + ${tests}/events/different_events.cpp ) set(t_includes diff --git a/src/events/event.cpp b/src/events/event.cpp index 8fe54ed..2e0b7fe 100644 --- a/src/events/event.cpp +++ b/src/events/event.cpp @@ -9,6 +9,7 @@ using std::function; using std::unordered_map; using std::queue; using std::bitset; +using std::pair; using traits::tr_set; using dataStorage::DataStorage; using dataStorage::DoubleLinkedList; @@ -67,29 +68,50 @@ namespace events { delete eventF; } + + void EventManager::fire_during_iteration(vectorofFunctions* functions, std::shared_ptr event) { + dataStorage::DoubleLinkedListNode* eventF = functions->head; + while (eventF) { + (*(eventF->data))(event); + if (event->result != PASS) { + break; + } + eventF = eventF->getNext(); + } + } + void EventManager::iterateOverEvents() { lateRunEvents->head->data->initialEvent = true; iterating = true; InfoManager* manager(InfoManager::getManager()); do { + // Getting activation bitset std::shared_ptr event = this->lateRunEvents->head->data; + unsigned char event_traits_amount = event->activation_traits.size(); this->lateRunEvents->erase(this->lateRunEvents->head); bitset traits_bitset( manager->trset_to_bitset(event->activation_traits) ); - if (!this->registered_events[event->activation_traits.size()].contains(traits_bitset)) { + + // Checking membership of such traits + if (!this->registered_events[event_traits_amount].contains(traits_bitset)) { continue; } - vectorofFunctions* functions = this->registered_events[ - event->activation_traits.size() - ].at(traits_bitset); - dataStorage::DoubleLinkedListNode* eventF = functions->head; - while (eventF) { - (*(eventF->data))(event); - if (event->result != PASS) { - break; + + // Actual event firing + fire_during_iteration(this->registered_events[event_traits_amount].at(traits_bitset), event); + + // Running through registered events of size below current + for (; event_traits_amount > 0; event_traits_amount--) { + for (auto& [i_bitset, i_receivers] : registered_events[event_traits_amount-1]) { + if ( + i_bitset.count() + != + (traits_bitset & i_bitset).count() + ) continue; + assert(true); + fire_during_iteration(i_receivers, event); } - eventF = eventF->getNext(); } } while (this->lateRunEvents->head); iterating = false; diff --git a/src/events/event.hpp b/src/events/event.hpp index 96fb972..ae566d4 100644 --- a/src/events/event.hpp +++ b/src/events/event.hpp @@ -119,6 +119,7 @@ namespace events { receivers_map registered_events[MAX_TRAITS_IN_TRSET]; dataStorage::DoubleLinkedList>* lateRunEvents; void iterateOverEvents(); + void fire_during_iteration(vectorofFunctions*, std::shared_ptr); static EventManager* instance; volatile bool iterating = false; EventManager(); diff --git a/tests/events/different_events.cpp b/tests/events/different_events.cpp new file mode 100644 index 0000000..89981f9 --- /dev/null +++ b/tests/events/different_events.cpp @@ -0,0 +1,54 @@ +#include +#include "../../src/events/event.hpp" +#include "../leaks.hpp" + +using namespace std; +using namespace dataStorage; + +namespace events { + namespace { + static unsigned char called1 = 0; + static unsigned char called2 = 0; + static unsigned char called3 = 0; + + void dif_ev_helper1(shared_ptr e) { called1++; } + void dif_ev_helper2(shared_ptr e) { called2++; } + void dif_ev_helper3(shared_ptr e) { called3++; } + } + + TEST(events, traits_double_call) { + MemoryLeakDetector _; + called1 = 0; + called2 = 0; + called3 = 0; + EventManager* manager = EventManager::getManager(); + Function* func1 = manager->registerForEvent({ 201 }, &dif_ev_helper1); + Function* func2 = manager->registerForEvent({ 202 }, &dif_ev_helper1); + Function* func3 = manager->registerForEvent({ 201, 202 }, &dif_ev_helper2); + + // Testing + shared_ptr event = shared_ptr(new Event({ 201, 202 })); + ASSERT_EQ(called1, 0); + ASSERT_EQ(called2, 0); + ASSERT_EQ(called3, 0); + manager->fireEvent(event); + ASSERT_EQ(called1, 2); + ASSERT_EQ(called2, 1); + ASSERT_EQ(called3, 0); + event->changeActivationTraits({ 201 }); + manager->fireEvent(event); + ASSERT_EQ(called1, 3); + ASSERT_EQ(called2, 1); + ASSERT_EQ(called3, 0); + event->changeActivationTraits({ 201, 202 }); + manager->fireEvent(event); + ASSERT_EQ(called1, 5); + ASSERT_EQ(called2, 2); + ASSERT_EQ(called3, 0); + + // Closing + manager->unregisterForEvent({ 201 }, func1); + manager->unregisterForEvent({ 202 }, func2); + manager->unregisterForEvent({ 201, 202 }, func3); + } +}