added dispatch::discard to clear pools of events (close #312)

This commit is contained in:
Michele Caini
2019-09-10 22:54:56 +02:00
parent e80adc2799
commit b2fad7a567
2 changed files with 68 additions and 10 deletions

View File

@@ -4,7 +4,9 @@
#include <vector>
#include <memory>
#include <cstddef>
#include <utility>
#include <algorithm>
#include <type_traits>
#include "../config/config.h"
#include "../core/family.hpp"
@@ -37,6 +39,7 @@ class dispatcher {
struct base_wrapper {
virtual ~base_wrapper() = default;
virtual void publish() = 0;
virtual void clear() = 0;
};
template<typename Event>
@@ -45,12 +48,17 @@ class dispatcher {
using sink_type = typename signal_type::sink_type;
void publish() override {
for(const auto &event: events[current]) {
signal.publish(event);
const auto length = events.size();
for(std::size_t pos{}; pos < length; ++pos) {
signal.publish(events[pos]);
}
events[current++].clear();
current %= std::extent<decltype(events)>::value;
events.erase(events.cbegin(), events.cbegin()+length);
}
void clear() override {
events.clear();
}
sink_type sink() ENTT_NOEXCEPT {
@@ -64,13 +72,12 @@ class dispatcher {
template<typename... Args>
void enqueue(Args &&... args) {
events[current].emplace_back(std::forward<Args>(args)...);
events.emplace_back(std::forward<Args>(args)...);
}
private:
signal_type signal{};
std::vector<Event> events[2];
int current{};
std::vector<Event> events;
};
struct wrapper_data {
@@ -205,6 +212,27 @@ public:
assure<std::decay_t<Event>>().enqueue(std::forward<Event>(event));
}
/**
* @brief Discards all the events queued so far.
*
* If no types are provided, the dispatcher will clear all the existing
* pools.
*
* @tparam Event Type of events to discard.
*/
template<typename... Event>
void discard() {
if constexpr(sizeof...(Event) == 0) {
std::for_each(wrappers.begin(), wrappers.end(), [](auto &&wdata) {
if(wdata.wrapper) {
wdata.wrapper->clear();
}
});
} else {
(assure<std::decay_t<Event>>().clear(), ...);
}
}
/**
* @brief Delivers all the pending events of the given type.
*
@@ -228,9 +256,7 @@ public:
*/
void update() const {
for(auto pos = wrappers.size(); pos; --pos) {
auto &wdata = wrappers[pos-1];
if(wdata.wrapper) {
if(auto &wdata = wrappers[pos-1]; wdata.wrapper) {
wdata.wrapper->publish();
}
}

View File

@@ -10,6 +10,10 @@ struct one_more_event {};
ENTT_NAMED_TYPE(an_event)
struct receiver {
static void forward(entt::dispatcher &dispatcher, const an_event &event) {
dispatcher.enqueue(event);
}
void receive(const an_event &) { ++cnt; }
void reset() { cnt = 0; }
int cnt{0};
@@ -39,6 +43,16 @@ TEST(Dispatcher, Functionalities) {
ASSERT_EQ(receiver.cnt, 3);
dispatcher.enqueue<an_event>();
dispatcher.discard<an_event>();
dispatcher.update();
dispatcher.enqueue<an_event>();
dispatcher.discard();
dispatcher.update();
ASSERT_EQ(receiver.cnt, 3);
receiver.reset();
an_event event{};
@@ -51,3 +65,21 @@ TEST(Dispatcher, Functionalities) {
ASSERT_EQ(receiver.cnt, 0);
}
TEST(Dispatcher, StopAndGo) {
entt::dispatcher dispatcher;
receiver receiver;
dispatcher.sink<an_event>().connect<&receiver::forward>(dispatcher);
dispatcher.sink<an_event>().connect<&receiver::receive>(receiver);
dispatcher.enqueue<an_event>();
dispatcher.update();
ASSERT_EQ(receiver.cnt, 1);
dispatcher.sink<an_event>().disconnect<&receiver::forward>(dispatcher);
dispatcher.update();
ASSERT_EQ(receiver.cnt, 2);
}