// Message.h #ifndef trf__Message_H #define trf__Message_H // Messages are passed from senders (class trf::TrfObject) to // receivers (class trf::Reporter). They include the following // information: // 1. pointer to reporting object (may be null) // 2. string indicating the location from which message was broadcast // 3. data // // There are five levels of messages. // AbsMessage is the abstract base for all messages // SimpleMessage adds the location // DataMessage adds data to SimpleMessage // SenderMessage adds the sender to SimpleMessage // Message = combines DataMessage and SenderMessage // // This structure allows users of AbsMessage to use dynamic casts to // independently determine the type of the sender or the data. // The methods DataMessage::is(msg) and // SenderMessage::is(msg) may be used for this purpose. // // Senders will send messages of type Message with calling object // as the sender. Free functions use DataMessage. // #include #include namespace trf { //********************************************************************** // Abstract interface for all messages. class AbsMessage { public: // Destructor. virtual ~AbsMessage() { } // Output stream. virtual void ostr(std::ostream& strm) const =0; // Return the address of the sender. virtual const void* sender_address() const { return 0; } // Return the location from which the message was sent. virtual std::string location() const { return ""; } }; //********************************************************************** // Message with location only. class SimpleMessage : public AbsMessage { // The location. std::string _loc; public: // Constructor. SimpleMessage(std::string loc) : _loc(loc) { } // Destructor. ~SimpleMessage() { } // Return the location. std::string location() const { return _loc; } // Display contents. void ostr(std::ostream& strm) const { strm << "Message from location " << location(); } }; //********************************************************************** // Message with location and data. template class DataMessage : public virtual SimpleMessage { private: // data // Data. const Data& _data; public: // static methods // Return if an AbsMessage is of this type. static bool is(const AbsMessage& msg) { return dynamic_cast*>(&msg) != 0; } public: // methods // Constructor. DataMessage(std::string loc, const Data& data) : SimpleMessage(loc), _data(data) { } // Return the data. const Data& data() const { return _data; } // Display contents. void ostr(std::ostream& strm) const { strm << "Data message from location " << location(); } }; //********************************************************************** // Message with sender and location. template class SenderMessage : public virtual SimpleMessage { private: // data // The sender. const Sender& _sender; public: // static methods // Return if an AbsMessage is of this type. static bool is(const AbsMessage& msg) { return dynamic_cast*>(&msg) != 0; } public: // methods // Constructor. SenderMessage(const Sender& sender, std::string loc) : SimpleMessage(loc), _sender(sender) { } // Return the address of the sender. const void* sender_address() const { return &_sender; } // Return the sender. const Sender& sender() const { return _sender; } }; //********************************************************************** // Complete message: sender, location and data. template class Message : public SenderMessage, public DataMessage { public: // methods // Constructor. Message(const Sender& sender, std::string loc, const Data& data) : SimpleMessage(loc), SenderMessage(sender,loc), DataMessage(loc, data) { } // Display contents. void ostr(std::ostream& strm) const { SenderMessage::ostr(strm); } }; //********************************************************************** // Output stream. inline std::ostream& operator<<(std::ostream& lhs, const AbsMessage& rhs) { rhs.ostr(lhs); return lhs; } } // end namespace trf #endif