3

I have a C++ Windows application. I am dealing with a publisher-subscriber situation, where one of my classes (publisher) generates data periodically and hands it off to another class (subscriber) which is constantly waiting to receive notification from the publisher. I am new to design patterns, and I looked up common implementations for publisher subscriber models, I noticed they are usually quite old, and they usually involve maintaining lists of pointers to objects. I was wondering if there is a better way of coding publisher subscriber model using C++ 11. Or using an entirely different model altogether in place of publisher - subscriber. If you can name some interesting features or approaches, I will read documentation for them, write an implementation and add it here for further review.

Update : I said I would post sample code. First, Boost Signals 2 as recommended by Jens really works great. My code is not quite different from the beginner sections on http://www.boost.org/doc/libs/1_55_0/doc/html/signals2/tutorial.html

The Vivandiere
  • 3,059
  • 3
  • 28
  • 50
  • 1
    The problem has not changed, the solution has not changed either. There are different considerations that are not present in the question, but for the overall concern: you do not need to implement all of the code that moves the data from the producer to the consumer, you can use existing components (a sequence container with external synchronization) that hide the complexity of the data structure itself. – David Rodríguez - dribeas Jul 31 '14 at 19:30
  • @DavidRodríguez-dribeas "you can use existing components (a sequence container with external synchronization)" Could you please elaborate this a little, I am quite new to all this. By synchronization, do you mean for handling concurrency related issues? Or, do you mean an external agency will have both the publisher and subscribers in its scope, and thus will be able to manage all of them. All this being done in a single thread. – The Vivandiere Jul 31 '14 at 20:09
  • For the simplest solution (not necessarily the best or worst for your problem) consider a synchronization queue combine a std::deque, a mutex and a condition variable. The publisher locks, push_back, signal, the consumer locks, checks if there is data and takes it or if there isn't waits on the condition variable. – David Rodríguez - dribeas Jul 31 '14 at 20:12

3 Answers3

5

Take a look at a signal library, e.g. Boost.Signals2 or libsigc++. They provide an abstraction to define a signal in your class to which clients can connect. All the logic to store connections etc is implemented there.

Jens
  • 9,058
  • 2
  • 26
  • 43
3

You can store a vector of functions, here's a quick and dirty way:

template<class T>
class dispatcher
{
    std::vector<std::function<void(T)> > functions;
public:
    void subscribe(std::function<void(T)> f)
    {
        functions.push_back(f);
    }

    void publish(T x)
    {
        for(auto f:functions) f(x);
    }
};

This doesn't have an unsubscribe(you would have to use a map for that).

However, this isn't thread-safe. If you want thread safety, you should you Boost.Signals2.

Paul Fultz II
  • 17,682
  • 13
  • 62
  • 59
1

Well, if you want modern, really modern alternative, maybe, besides Boost.Signals2, as mentioned by Jens, you could try functional reactive programming paradigm.

tonylo
  • 3,311
  • 3
  • 28
  • 27
Germán Diago
  • 7,473
  • 1
  • 36
  • 59