fix event_bus rvalue can't bind to lvalue
Some checks failed
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (push) Successful in 1m49s
linux-mips64-gcc / linux-gcc-mips64el (Debug) (push) Successful in 1m48s
linux-mips64-gcc / linux-gcc-mips64el (Release) (push) Failing after 1m48s
linux-arm-gcc / linux-gcc-armhf (push) Successful in 1m58s
linux-x64-gcc / linux-gcc (Debug) (push) Successful in 1m57s
linux-x64-gcc / linux-gcc (Release) (push) Successful in 2m6s

This commit is contained in:
tqcq 2024-04-04 02:16:30 +00:00
parent d03bc5b78d
commit 9de3404627
2 changed files with 52 additions and 9 deletions

View File

@ -1,6 +1,7 @@
#ifndef SLED_EVENT_BUS_EVENT_BUS_H #ifndef SLED_EVENT_BUS_EVENT_BUS_H
#define SLED_EVENT_BUS_EVENT_BUS_H #define SLED_EVENT_BUS_EVENT_BUS_H
#include "sled/exec/detail/invoke_result.h"
#include "sled/sigslot.h" #include "sled/sigslot.h"
#include "sled/synchronization/mutex.h" #include "sled/synchronization/mutex.h"
#include <typeindex> #include <typeindex>
@ -13,7 +14,10 @@ class Subscriber;
namespace internal { namespace internal {
template<typename Event> template<typename Event>
using RawType = typename std::remove_cv<typename std::remove_reference<Event>::type>::type; using RawType = typename std::remove_cv<typename std::remove_reference<Event>::type>::type;
} template<typename T>
using EnableNotVolatile = typename std::enable_if<!std::is_volatile<T>::value>;
// using RawType = typename std::remove_const<typename std::remove_reference<Event>::type>::type;
}// namespace internal
namespace { namespace {
@ -36,16 +40,16 @@ public:
return cleanup_handler; return cleanup_handler;
} }
void Post(EventBus *bus, Event event) void Post(EventBus *bus, const Event &event)
{ {
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(std::forward<Event>(event)); } if (iter != signals_.end()) { iter->second(event); }
} }
template<typename C> template<typename C, typename F>
void Subscribe(EventBus *bus, C *instance, void (C::*method)(Event)) void Subscribe(EventBus *bus, C *instance, F &&method)
{ {
sled::SharedMutexWriteLock lock(&shared_mutex_); sled::SharedMutexWriteLock lock(&shared_mutex_);
auto iter = signals_.find(bus); auto iter = signals_.find(bus);
@ -118,16 +122,17 @@ public:
EventBus(const EventBus &) = delete; EventBus(const EventBus &) = delete;
EventBus &operator=(const EventBus &) = delete; EventBus &operator=(const EventBus &) = delete;
template<typename Event, typename U = internal::RawType<Event>> template<typename Event>
void Post(Event &&event) void Post(Event &&event)
{ {
using U = typename internal::RawType<Event>;
EventRegistry<U>::Instance().Post(this, std::forward<Event>(event)); EventRegistry<U>::Instance().Post(this, std::forward<Event>(event));
} }
template<typename Event, typename From> template<typename Event, typename From>
void PostTo(From &&value) void PostTo(From &&value)
{ {
using U = internal::RawType<Event>; using U = typename internal::RawType<Event>;
EventRegistry<U>::Instance().Post(this, std::forward<From>(value)); EventRegistry<U>::Instance().Post(this, std::forward<From>(value));
} }
@ -136,7 +141,7 @@ public:
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))
{ {
using U = internal::RawType<Event>; using U = typename internal::RawType<Event>;
{ {
sled::MutexLock lock(&mutex_); sled::MutexLock lock(&mutex_);
auto iter = cleanup_handlers_.find(std::type_index(typeid(U))); auto iter = cleanup_handlers_.find(std::type_index(typeid(U)));
@ -151,7 +156,7 @@ public:
template<typename Event, typename C> template<typename Event, typename C>
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)
{ {
using U = internal::RawType<Event>; using U = typename internal::RawType<Event>;
EventRegistry<U>::Instance().Unsubscribe(this, instance); EventRegistry<U>::Instance().Unsubscribe(this, instance);
{ {
sled::MutexLock lock(&mutex_); sled::MutexLock lock(&mutex_);

View File

@ -186,4 +186,42 @@ TEST_SUITE("EventBus")
CHECK_EQ(subscriber1.a, 3); CHECK_EQ(subscriber1.a, 3);
CHECK_EQ(subscriber2.a, 3); CHECK_EQ(subscriber2.a, 3);
} }
TEST_CASE("msg convert test")
{
struct Msg {
int value;
};
std::atomic<int> counter;
struct SubscribeCounter : public sled::EventBus::Subscriber<> {
SubscribeCounter(std::atomic<int> *counter) : counter_(counter) {}
void OnEvent(Msg msg) { counter_->fetch_add(msg.value); }
std::atomic<int> *counter_;
};
SubscribeCounter subscriber{&counter};
sled::EventBus bus;
bus.Subscribe(&subscriber, &SubscribeCounter::OnEvent);
Msg msg{1};
bus.Post(msg);
CHECK_EQ(counter.load(), 1);
bus.Post(const_cast<const Msg &>(msg));
CHECK_EQ(counter.load(), 2);
bus.Post(std::move(msg));
CHECK_EQ(counter.load(), 3);
bus.Post(const_cast<const Msg &>(msg));
CHECK_EQ(counter.load(), 4);
// volatile Msg volatile_msg{1};
// bus.Post(volatile_msg);
// CHECK_EQ(counter.load(), 4);
}
} }