GLProgramming.com

home :: about :: development guides :: irc :: forums :: search :: paste :: links :: contribute :: code dump

-> Click here to learn how to get live help <-


New Paste :: Recent Pastes:: Add Line Numbers


generic message passing by godecho
#ifndef MESSAGE_H_INCLUDED_
#define MESSAGE_H_INCLUDED_

template <typename tIdType>
class Message
{
    public:
        
        typedef tIdType id_type;
        const tIdType ID;
        
        Message(const tIdType& id)
            : ID(id)
        {
        
        }
        
        virtual ~Message(void)
        {
        
        }
        
        template <class Derived>
        Derived polymorphicDowncast(void) const            // This is essentially boost::polymorphic_downcast
        {
            assert(dynamic_cast<Derived>(this) == this);    // This ensures a non-zero pointer returned, and that it is casting to a derived type.
                                                            // Warning: Because polymorphicDowncast uses assert(), it violates the One Definition Rule (ODR) if NDEBUG is inconsistently defined across translation units. [See ISO Std 3.2]
            return static_cast<Derived>(this);
        }
        
        

};

#endif  // #ifndef MESSAGE_H_INCLUDED_

#ifndef MESSAGE_MANAGER_H_INCLUDED_
#define MESSAGE_MANAGER_H_INCLUDED_

#include <map>

#include "Message.h"

template <class tMessage>
class MessageManager
{
    public:
        
        typedef tMessage message_type;
        typedef typename message_type::id_type message_id_type;
        typedef void(*message_callback)(const message_type* message);   // We'd be better off using functors rather than function pointers
        
        MessageManager(void)
        {
        
        }
        
        virtual ~MessageManager(void)
        {
        
        }
        
        virtual void acceptMessage(const message_type* message)
        {
            typedef std::multimap<message_id_type, message_callback>::iterator       cbItr;
            typedef std::multimap<message_id_type, message_callback>::const_iterator cbCItr;
            
            std::pair<cbItr, cbItr> callbackItrs = mMessageCallbacks.equal_range(message->ID);
            
            for(cbItr cb = callbackItrs.first; cb != callbackItrs.second; ++cb)
            {
                message_callback myCb = (*cb).second;
                (*myCb)(message);
            }
        }
        
        virtual void registerCallback(const message_id_type& messageId, const message_callback callback)
        {
            mMessageCallbacks.insert(std::make_pair(messageId, callback));
        }
        
        template <class Iterator>
        void registerCallback(Iterator first, Iterator last, const message_callback callback)
        {
            for( ; first != last; ++first)
            {
                registerCallback((*first), callback);
            }
        };
        
    protected:
    
        std::multimap<message_id_type, message_callback> mMessageCallbacks;
};

#endif // #ifndef MESSAGE_MANAGER_H_INCLUDED_

#ifndef REAL_MESSAGES_H_INCLUDED_
#define REAL_MESSAGES_H_INCLUDED_

#include <string>

#include "Message.h"

class RealMessageA : public Message<std::string>
{
    public:

        RealMessageA::RealMessageA(void)
            : Message("RealMessageA")
        {
        }

        RealMessageA::~RealMessageA(void)
        {
        }
        
        int arrrr;
};

class RealMessageB : public Message<std::string>
{
    public:

        RealMessageB::RealMessageB(void)
            : Message("RealMessageB")
        {
        }

        RealMessageB::~RealMessageB(void)
        {
        }
        
        double alpha;
        double beta;
};


#endif // #ifndef REAL_MESSAGES_H_INCLUDED_

#include <iostream>
#include <string>
#include <cassert>

#include "MessageManager.h"
#include "RealMessages.h"

void printArrrr(const Message<std::string>* message)
{
    assert(message != 0);
    const RealMessageA* mymessage = message->polymorphicDowncast<const RealMessageA*>();
    
    std::cout << mymessage->arrrr << std::endl;
}

void printAlphaBeta(const Message<std::string>* message)
{    
    assert(message != 0);
    const RealMessageB* mymessage = message->polymorphicDowncast<const RealMessageB*>();
    
    std::cout << mymessage->alpha << ' ' << mymessage->beta << std::endl;
}

int main(int argc, char** argv)
{
    MessageManager< Message<std::string> > mess;
    
    mess.registerCallback("RealMessageA", printArrrr);
    
    RealMessageA messageA;
    messageA.arrrr = 4;
    
    RealMessageB messageB;
    messageB.alpha = 3.14;
    messageB.beta  = 0.0;
    
    mess.acceptMessage(&messageA);  // prints 4
    mess.acceptMessage(&messageB);  // prints nothing, no callbacks registered for messageB type
    
    mess.registerCallback("RealMessageB", printAlphaBeta);
    mess.acceptMessage(&messageB);  // prints 3.14 0
}