lundi 25 juillet 2022

managing global state with parameterization (without singleton) but with a templated class

I am writing a small pub/sub application in c++14/17 for practice and self-learning. I say 14/17 because the only feature of c++17 I have used for this project so far has been the std::scoped_lock.

In this toy application, the publishers and subscribers are on the same OS process (same compiled binary).

A reasonable thing is to do in this case, is have a single class that stores the messages in an std::unordered_map<std::string, std:enque>. I plan on instantiating this class in main and passing it to the constructors of the publishers and subscribers.

The problem comes when I attempt to hold the messages into a custom queue class, with a template for different messages; for example using protobuf.

Please consider the following:

// T here represents different
// protobuf classes
template <class T>
class Queue {
public:
    std::mutex mutex_;

    void enqueueMessage(const T* message);
    const T* dequeueMessage();
    const int length() { return messages_.size();};
private:
    std::string id_;
    std::deque<const T*> messages_;
};

class Node
{
public:
    Node();
    template <class T>
    Publisher<T>* createPublisher(std::string const topic_name, Broker broker);
};

class Broker {
    public:
        template <class T>
        Publisher<T>* createPublisher(std::string const topic_name);
    private:
        /** THE PROBLEM IS HERE **/
        std::unordered_map<std::string, Queue<T*>*> queues_;
};

int main(int argc, char** argv)
{
    // this object holds the global state
    // and will be passed in when needed
    auto broker = std::make_shared<Broker>();

    EmployeeMessage empMessage = EmployeeMessage(/* params */);
    WeatherMessage  weatherMessage = WeatherMessage(/* params */);
    
    auto nodeEmp = std::make_shared<Node>();
    auto nodeWeather = std::make_shared<Node>();

    nodeEmp.createPublisher<EmployeeMessage>("name1", broker);
    nodeWeather.createPublisher<EmployeeMessage>("name2", broker);
    

}

The queues_ member of the Broker class cannot have a Type T because the Broker is not a template class.

I cannot make Broker into a template class because then I would have an instance of broker for each type of message.

How can I fix this design?

Aucun commentaire:

Enregistrer un commentaire