Hi,

I have a Blackboard object which is a singleton, what it does is store the message and the reciever. The challenge is that the blackboard will send an alert to the reciever and the reciever have to check the blackboard for the message.

class Subscriber{
public:
    virtual ~Subscriber() {}
    virtual void update() {}
    virtual void alert(){ newMessage = true; }
    virtual void noMessage(){ newMessage = false; }
private:
    std::string message;
    bool newMessage;
};

class Blackboard{
public:

    static Blackboard* getInstance();
    ~Blackboard(){}
    void subscribe(Subscriber* s){ subscribers.push_back(s); }
    void unSubscribe(Subscriber* s){ subscribers.remove(s); }
    void post(std::string msg, Subscriber* toWhom);
    void notify(Subscriber* s);
    void notifyAll();

private:
    Blackboard(): message(""){}
    std::string message;
    std::list<Subscriber*> subscribers;
    static Blackboard* instance;

I cant use toWhom->update(), I know i can do it this way inside post() method. The thing is: I need to use alert(). I cant explain it well but all the blackboard do is notify its subscriber and the subscriber will have to check the blackboard when notified then the subscriber will act based on the message. I cant think of a way on how to do this.

Edited 2 Years Ago by HuePig

Subscriber::update, Subscriber::alter and Subscriber::noMessage all sound like they are doing the same thing and should be a single method.

For the operation you want to perform you are missing an operation in Blackboard because there is no way to get the current message, you need a BlackBoard::getMessage method.

Blackboard::notify and Blackboard::notifyAll sound like they should not be public methods of Blackboard. You post data to the Blackboard, it decides if anyone needs notifying, so the notify operations should not be something that are available for anyone they are internal operations.

Finally Blackboard::post has an odd prototype, in the Observer pattern the idea us that the publisher does not need to have any knowledge of who is receiving the data, they just publish (post) the data and the publishing object (Blackboard in this case) takes care of informing all subscribers. In this case Blackboard::post would have the prototype Blackboard::post(const std::string& msg)

How can I make the subscriber check for the message on the condition that the blackboard have a message addressed to them specifically? The thing is that subscriber objects have to check for messages when they are alerted. I can't think of a way to do this without using the subscriber pointer that will be stored in the blackboard object.
Basically, Subscriber will need autonomy in checking for messages, all the blackoad will do is store the message and alert the subscriber objects. I cant think of a way to do this or is *subscriber->update() in post() the only way?

note that on my previous build I had Subscriber::update(message) and this is called in Blackboard::notify(subscriber*, message) by *subscriber->update(message).

this works, but I was told to redisign the blackboard so that the subscriber themselves check for the messages and that blackboards will only store the messages and notify the recipient.

It seams to me the blackboard needs to store the message along with the user who posted it. Then the subscribers will hold a list of the users they are subscribing to. When a new message is added all subscribers would get notified of the user that posted and only the subscribers the subscribed to that user would then call back and get the message.

This definately does not sound like the observer pattern (which is OK you never said that you were implementing that) since in the observer pattern the publisher (thing adding the message) has no knowledge of who is subscribing where as in your implementation it is paramount that they do.

I think that your subscribers need to have and identifier (be that a number or a string) because otherwise the publisher needs to somehow know the pointer to the subscriber, with an id the ids used by the program can be static global data or even exist in a configuration file.

But then you also have the problem of only storing 1 string because in a multi-threaded program it seems entirely possible that you may get multiple updates happening on Blackboard in different threads it would be possible for a Blackboard::post call in 1 thread to overwrite the message from the previous Blackboard::post call before the subscribers had picked it up.

You then need to store a message for every possible id, luckily C++ has a structure for this ... std::map.

However ignoring the multi-threaded case and sticking with a single string you have 2 options both use a modified post in the form of void Blackboard::post(std::string msg, Identifier toWhom); (note I am generalising the type of the identifier as Identifier you can still make this either a string or an integer)

1: Blackboard::post checks all the identities of its registered subscribers and only calls Subscriber::update on subscribers with a matching id.

2: Blackboard::post calls all its registered subscribers but Subscriber::update is modified to take the id of the subscriber the message is for and only calls getMessage if the message is for itself.

Additionally your subscriber class has to be modified to include an Identifier.

Use of identifiers instead of pointer to class separates out of the logic of what is going on from data (pointer value) that is only available at run time and which changes from run to run.

This article has been dead for over six months. Start a new discussion instead.