I am working on an EventDispatcher
class that implements the publish-subscribe pattern. Here is a simplified interface:
class EventDispatcher
{
friend Subscription;
public:
void publish(const std::string& event_name, std::shared_ptr<Event> event);
std::unique_ptr<Subscription> subscribe(const std::string& event_name, std::unique_ptr<Callback> callback);
private:
std::unordered_map<std::string, some_container<std::unique_ptr<Callback>>> m_subscriptions;
}
This class needs to hold a collection of callback functions for each type of event. To do this I use std::unordered_map
, which maps from event names to a container of Callback
functions.
The subscribe
function returns a unique pointer to an Subscription
instance. The job of this object is to unsubscribe from its destructor. Now, the question is how does the Subscription
class unsubscribe?
It needs to remove a particular Callback pointer from some_container
. Insertion, deletion and forward iteration over some_container
needs to be fast. I considered the following method:
- Subscription stores the insertion index into
some_container
for the Callback pointer that it manages. - The Subscription class's destructor then removes the Callback pointer from
some_container
at the insertion index.
That's all very simple. The problem now is which container do I use for some_container
? Using the insertion index requires that the contents do not move when I remove one element. This rules out any linked list based containers in addition to std::vector. Is there common type of container that meets these requirements or do I need to create my own?
Why not multimap?
To preempt one suggestion, why not use multimap<Subscription*, std::unique_ptr<Callback>>
for some_container
? Whilst this would certainly work, I believe that multimap does not store its values contiguously in memory, which will probably hurt when I come to iterate over all of the callbacks subscribed to a particular event.
Aucun commentaire:
Enregistrer un commentaire