I have an event manager that is implemented as a table of std::unique_ptr<CallbackWrapperBase> objects.
Callables subscribe for specific events using the
template <type EventType>
void subscribe(std::function<void(const EventType&)>);
templated member functions.
What I want to do is make the functions return handles so that I can unsubscribe callables in O(1) time given that the table is basically a vector of vectors.
While the code works, I think it looks hack-ish and I was wondering if there is any pattern/idiom in order to properly deal with this issue.
Here is the part of the code:
struct CallbackHandle
{
CallbackHandle(EventBus& bus, std::size_t type_index, std::size_t position_index) : m_bus(bus), m_type_index(type_index), m_position_index(position_index) {}
void changePosition(std::size_t position_index) { m_position_index = position_index; }
std::size_t getTypeIndex() const {return m_type_index; }
std::size_t getPositionIndex() const { return m_position_index; }
void unsubscribe()
{
m_bus.unsubscribe(*this);
}
std::size_t m_type_index;
std::size_t m_position_index;
EventBus& m_bus;
};
struct CallbackWrapperBase
{
.
.
void setHandle(CallbackHandle& handle) { m_handle = &handle; }
void notifyHandle(std::size_t new_position_index) { if (m_handle) m_handle->changePosition(new_position_index); }
CallbackHandle* m_handle = nullptr;
};
public:
//Subscribes an event handle to the appropriate events.
template <typename EventType>
std::unique_ptr<CallbackHandle> subscribe(Callback<EventType> callback)
{
auto type_index = Event<EventType>::typeIndex();
if (type_index >= m_callback_table.size())
m_callback_table.resize(type_index+1);
std::unique_ptr<CallbackWrapperBase> ptr(new CallbackWrapper<EventType>(callback));
m_callback_table[type_index].push_back(std::move(ptr));
std::unique_ptr<CallbackHandle> handle(
new CallbackHandle(*this, type_index, m_callback_table.size()-1));
m_callback_table[type_index].back()->setHandle(*handle.get());
return std::move(handle);
}
//Unsubscribe an event handle from the events it's registered on.
void unsubscribe(const CallbackHandle& handle)
{
auto type_index = handle.getTypeIndex();
m_callback_table[type_index].back()->notifyHandle(handle.getPositionIndex());
std::swap(m_callback_table[type_index][handle.getPositionIndex()], m_callback_table[type_index].back());
m_callback_table[type_index].pop_back();
}
Any help is much appreciated!
Aucun commentaire:
Enregistrer un commentaire