mardi 30 décembre 2014

c++ container with constant element indices on insertion and removal

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:



  1. Subscription stores the insertion index into some_container for the Callback pointer that it manages.

  2. 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