fix event_bus
This commit is contained in:
parent
bf1584c750
commit
65fe7acded
@ -10,6 +10,11 @@ namespace sled {
|
|||||||
class EventBus;
|
class EventBus;
|
||||||
class Subscriber;
|
class Subscriber;
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
template<typename Event>
|
||||||
|
using RawType = typename std::remove_cv<typename std::remove_reference<Event>::type>::type;
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template<typename Event>
|
template<typename Event>
|
||||||
@ -36,7 +41,7 @@ public:
|
|||||||
sled::SharedMutexReadLock lock(&shared_mutex_);
|
sled::SharedMutexReadLock lock(&shared_mutex_);
|
||||||
if (signals_.empty()) { return; }
|
if (signals_.empty()) { return; }
|
||||||
auto iter = signals_.find(bus);
|
auto iter = signals_.find(bus);
|
||||||
if (iter != signals_.end()) { iter->second(event); }
|
if (iter != signals_.end()) { iter->second(std::forward<Event>(event)); }
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename C>
|
template<typename C>
|
||||||
@ -113,33 +118,36 @@ public:
|
|||||||
EventBus(const EventBus &) = delete;
|
EventBus(const EventBus &) = delete;
|
||||||
EventBus &operator=(const EventBus &) = delete;
|
EventBus &operator=(const EventBus &) = delete;
|
||||||
|
|
||||||
template<typename Event>
|
template<typename Event, typename U = internal::RawType<Event>>
|
||||||
void Post(const Event &event)
|
void Post(Event &&event)
|
||||||
{
|
{
|
||||||
EventRegistry<Event>::Instance().Post(this, event);
|
EventRegistry<U>::Instance().Post(this, std::forward<Event>(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
// On<Event1> ([](const Event1 &){})
|
// On<Event1> ([](const Event1 &){})
|
||||||
template<typename Event, typename C>
|
template<typename Event, typename C, typename U = internal::RawType<Event>>
|
||||||
typename std::enable_if<std::is_base_of<sigslot::has_slots_interface, C>::value>::type
|
typename std::enable_if<std::is_base_of<sigslot::has_slots_interface, C>::value>::type
|
||||||
Subscribe(C *instance, void (C::*method)(Event))
|
Subscribe(C *instance, void (C::*method)(Event))
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
sled::MutexLock lock(&mutex_);
|
sled::MutexLock lock(&mutex_);
|
||||||
cleanup_handlers_[std::type_index(typeid(Event))] = EventRegistry<Event>::GetCleanupHandler();
|
auto iter = cleanup_handlers_.find(std::type_index(typeid(U)));
|
||||||
|
if (iter == cleanup_handlers_.end()) {
|
||||||
|
cleanup_handlers_[std::type_index(typeid(U))] = EventRegistry<U>::GetCleanupHandler();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EventRegistry<Event>::Instance().Subscribe(this, instance, method);
|
EventRegistry<U>::Instance().Subscribe(this, instance, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Event, typename C>
|
template<typename Event, typename C, typename U = internal::RawType<Event>>
|
||||||
typename std::enable_if<std::is_base_of<sigslot::has_slots_interface, C>::value>::type Unsubscribe(C *instance)
|
typename std::enable_if<std::is_base_of<sigslot::has_slots_interface, C>::value>::type Unsubscribe(C *instance)
|
||||||
{
|
{
|
||||||
EventRegistry<Event>::Instance().Unsubscribe(this, instance);
|
EventRegistry<U>::Instance().Unsubscribe(this, instance);
|
||||||
{
|
{
|
||||||
sled::MutexLock lock(&mutex_);
|
sled::MutexLock lock(&mutex_);
|
||||||
if (EventRegistry<Event>::Instance().IsEmpty(this)) {
|
if (EventRegistry<U>::Instance().IsEmpty(this)) {
|
||||||
auto iter = cleanup_handlers_.find(std::type_index(typeid(Event)));
|
auto iter = cleanup_handlers_.find(std::type_index(typeid(U)));
|
||||||
if (iter != cleanup_handlers_.end()) {
|
if (iter != cleanup_handlers_.end()) {
|
||||||
iter->second(this);
|
iter->second(this);
|
||||||
cleanup_handlers_.erase(iter);
|
cleanup_handlers_.erase(iter);
|
||||||
@ -148,8 +156,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EventBus *operator->() { return this; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sled::Mutex mutex_;
|
sled::Mutex mutex_;
|
||||||
std::unordered_map<std::type_index, std::function<void(EventBus *)>> cleanup_handlers_ GUARDED_BY(mutex_);
|
std::unordered_map<std::type_index, std::function<void(EventBus *)>> cleanup_handlers_ GUARDED_BY(mutex_);
|
||||||
|
@ -37,6 +37,21 @@ struct Subscriber : public sled::EventBus::Subscriber<> {
|
|||||||
|
|
||||||
TEST_SUITE("EventBus")
|
TEST_SUITE("EventBus")
|
||||||
{
|
{
|
||||||
|
TEST_CASE("RawType")
|
||||||
|
{
|
||||||
|
CHECK(std::is_same<int, sled::internal::RawType<int>>::value);
|
||||||
|
CHECK(std::is_same<int, sled::internal::RawType<const int>>::value);
|
||||||
|
CHECK(std::is_same<int, sled::internal::RawType<const int &>>::value);
|
||||||
|
CHECK(std::is_same<int, sled::internal::RawType<int &>>::value);
|
||||||
|
CHECK(std::is_same<int, sled::internal::RawType<int &&>>::value);
|
||||||
|
|
||||||
|
CHECK(std::is_same<int, sled::internal::RawType<volatile int>>::value);
|
||||||
|
CHECK(std::is_same<int, sled::internal::RawType<volatile const int>>::value);
|
||||||
|
CHECK(std::is_same<int, sled::internal::RawType<volatile const int &>>::value);
|
||||||
|
CHECK(std::is_same<int, sled::internal::RawType<volatile int &>>::value);
|
||||||
|
CHECK(std::is_same<int, sled::internal::RawType<volatile int &&>>::value);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("single thread")
|
TEST_CASE("single thread")
|
||||||
{
|
{
|
||||||
sled::EventBus bus;
|
sled::EventBus bus;
|
||||||
@ -92,7 +107,13 @@ TEST_SUITE("EventBus")
|
|||||||
struct AotmicEventSubscriber : public sled::EventBus::Subscriber<> {
|
struct AotmicEventSubscriber : public sled::EventBus::Subscriber<> {
|
||||||
virtual ~AotmicEventSubscriber() = default;
|
virtual ~AotmicEventSubscriber() = default;
|
||||||
|
|
||||||
void OnEvent(AtomicEvent event) { event.data.fetch_add(1); }
|
void OnEvent(AtomicEvent event)
|
||||||
|
{
|
||||||
|
++a;
|
||||||
|
event.data.fetch_add(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int a = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::atomic<int> value(0);
|
std::atomic<int> value(0);
|
||||||
@ -117,4 +138,30 @@ TEST_SUITE("EventBus")
|
|||||||
CHECK_EQ(invoke_count.load(), kPublishCount);
|
CHECK_EQ(invoke_count.load(), kPublishCount);
|
||||||
CHECK_EQ(value.load(), kPublishCount * kSubscriberCount);
|
CHECK_EQ(value.load(), kPublishCount * kSubscriberCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("same type")
|
||||||
|
{
|
||||||
|
struct Event {
|
||||||
|
int a;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Subscriber : public sled::EventBus::Subscriber<> {
|
||||||
|
void OnEvent(Event event) { a += event.a; }
|
||||||
|
|
||||||
|
int a = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
sled::EventBus bus;
|
||||||
|
Subscriber subscriber1;
|
||||||
|
Subscriber subscriber2;
|
||||||
|
bus.Subscribe<Event>(&subscriber1, &Subscriber::OnEvent);
|
||||||
|
bus.Subscribe<Event>(&subscriber2, &Subscriber::OnEvent);
|
||||||
|
bus.Post(Event{1});
|
||||||
|
CHECK_EQ(subscriber1.a, 1);
|
||||||
|
CHECK_EQ(subscriber2.a, 1);
|
||||||
|
Event e{1};
|
||||||
|
bus.Post(e);
|
||||||
|
CHECK_EQ(subscriber1.a, 2);
|
||||||
|
CHECK_EQ(subscriber2.a, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user