#pragma once #include "node.h" #include "chain.h" #include "memblock.h" #include "memstrm.h" class Receiver__SharedData; class Receiver__InheritanceSet; struct Receiver__HandlerEntry; class Receiver__MessageHandlerSet; class Receiver__Message; class Receiver__DynamicMessage; class Derivation; class Event; class DynamicMemoryStream; class MessageTap; //########################################################################## //########################## Receiver ################################ //########################################################################## // // It is suggested that calls to methods meant to be serviced by a receiver // be built through inline functions in the derived class, rather than // having to build the parameter block in the scope of the caller. Letting // the inline code build the parameter block is much cleaner, and allows the // message code numbers to be held inside the derived class, further // protecting against calling methods for objects not in a proper derivation // chain. // class Receiver: public Node { //########################################################################## // Shared Data Support // public: typedef Receiver__SharedData SharedData; SharedData* GetSharedData() const; static Derivation* GetClassDerivations(); Derivation* GetDerivation() const; static SharedData DefaultData; Logical IsDerivedFrom(Derivation& parent) const; Logical IsDerivedFrom(const char* parent) const; protected: const SharedData* sharedData; //########################################################################## // Construction and Destruction Support // protected: Receiver( ClassID class_ID, SharedData &shared_data ): Node(class_ID), sharedData(&shared_data) {} Receiver( PlugStream *stream, SharedData &shared_data ): Node(stream), sharedData(&shared_data) {} //########################################################################## // Messaging Support // public: typedef Receiver__Message Message; typedef Receiver__DynamicMessage DynamicMessage; typedef Receiver__InheritanceSet InheritanceSet; typedef Receiver__HandlerEntry HandlerEntry; typedef Receiver__MessageHandlerSet MessageHandlerSet; typedef void (Receiver::*Handler)(const Message*); typedef Enumeration MessageID; enum { AnyMessageID=0, WatcherChangedMessageID, LoadResourceFinishedMessageID, NextMessageID }; static const Handler NullHandler; void Receive(Message *What); virtual void Dispatch(Message *What) {Receive(What);} void DefaultMessageHandler(Message*); typedef void (Receiver::*ScanCallback)( Receiver::Message *message, Receiver *receiver ); MessageTap* MakeMessageTap( Derivation *derivation, ScanCallback callback ); MessageTap* MakeMessageTap( Derivation *derivation, ScanCallback callback, Receiver::MessageID matching_message, Receiver *match_receiver ); protected: static const HandlerEntry MessageHandlerEntries[]; // swapping the commented line for the following one due to inconsitincies // in the order of initialization for static member variables //static MessageHandlerSet MessageHandlers; static MessageHandlerSet& GetMessageHandlers(); //########################################################################## // Event Support // public: virtual void Receive(Event *event); void FlushEvents(int max_priority=-1); void FlushMatchingEvents( MessageID target_message, int max_priority=-1 ); void ProcessDeferredQueue(); //########################################################################## // Test Support // public: static Logical TestClass(); Logical TestInstance() const; }; //########################################################################## //###################### Receiver::Message ########################### //########################################################################## class Receiver__Message { public: #if defined(USE_SIGNATURE) friend int Is_Signature_Bad(const volatile Receiver__Message *); #endif size_t messageLength; Receiver::MessageID messageID; enum { ReliableBit, NextBit }; enum { ReliableFlag = 1 << ReliableBit }; LWord messageFlags; Receiver__Message( Receiver::MessageID id, size_t message_length ): messageID(id), messageLength(message_length), messageFlags(ReliableFlag) // HACK {} Logical TestInstance() const; }; //########################################################################## //################### Receiver::DynamicMessage ####################### //########################################################################## class Receiver__DynamicMessage: public DynamicMemoryStream { public: Receiver__DynamicMessage() {} Receiver__DynamicMessage( void *stream_start, size_t stream_size, size_t initial_offset=0 ): DynamicMemoryStream(stream_start, stream_size, initial_offset) {} Receiver__DynamicMessage( Receiver::MessageID message_ID, size_t size = sizeof(Receiver::Message) ); Receiver::Message* GetMessagePointer() {Check(this); return Cast_Object(Receiver::Message*, streamStart);} protected: MemoryStream& WriteBytes( const void *ptr, size_t number_of_bytes ); }; //########################################################################## //#################### ReceiverDataMessageOf ######################### //########################################################################## template class ReceiverDataMessageOf: public Receiver::Message { public: T dataContents; ReceiverDataMessageOf( Receiver::MessageID id, size_t message_length, const T& data ): Receiver::Message(id, message_length), dataContents(data) {} }; //########################################################################## //######################### MessageTap ############################### //########################################################################## class MessageTap: public Plug { //########################################################################## // MessageTap Functionality // public: MessageTap( Derivation *derivation, Receiver *client, Receiver::ScanCallback callback ); MessageTap( Derivation *derivation, Receiver *client, Receiver::ScanCallback callback, Receiver::MessageID matching_message, Receiver *match_receiver ); private: Receiver::ScanCallback scanCallback; Receiver* clientReceiver; Receiver* matchingReceiver; Receiver::MessageID matchingMessageID; public: void Scan( Receiver *receiver, Receiver::Message *message ); //########################################################################## // Memory Allocation // private: static MemoryBlock* GetAllocatedMemory(); public: void* operator new(size_t) { return GetAllocatedMemory()->New(); } void operator delete(void *where) { GetAllocatedMemory()->Delete(where); } //########################################################################## // Test support // public: Logical TestInstance() const; static Logical TestClass(); }; //########################################################################## //################## Receiver::InheritanceSet ######################## //########################################################################## // // NOTE: An InheritanceSet generated for a class should only be inherited by // other classes derived from that base class. If this is not done, // SEVERE run-time weirdness will happen // class Receiver__InheritanceSet SIGNATURED { public: Logical TestInstance() const; Enumeration GetEntryCount() {Check(this); return entryCount;} protected: Enumeration entryCount; Receiver__InheritanceSet() {} ~Receiver__InheritanceSet() {} }; //########################################################################## //################### Receiver::HandlerEntry ######################### //########################################################################## struct Receiver__HandlerEntry { Enumeration entryID; const char* entryName; Receiver::Handler entryHandler; }; #define MESSAGE_ENTRY(class,message)\ {\ class::message##MessageID,\ #message,\ (Receiver::Handler)&class::message##MessageHandler\ } //########################################################################## //################# Receiver::MessageHandlerSet ###################### //########################################################################## class Receiver__MessageHandlerSet: public Receiver__InheritanceSet { //########################################################################## // Constructors and Destructors // public: Receiver__MessageHandlerSet(Receiver::MessageID count, const Receiver::HandlerEntry handler_table[], const Receiver::MessageHandlerSet &inheritance) { Build(count, handler_table, &inheritance); } Receiver__MessageHandlerSet(Receiver::MessageID count, const Receiver::HandlerEntry handler_table[]) { Build(count, handler_table, NULL); } Receiver__MessageHandlerSet(const Receiver::MessageHandlerSet& source) { Build(0, NULL, &source); } Receiver__MessageHandlerSet() { messageHandlers = NULL; entryCount = 0; } ~Receiver__MessageHandlerSet(); protected: void Build( Receiver::MessageID count, const Receiver::HandlerEntry handler_table[], const Receiver::MessageHandlerSet *inheritance ); //########################################################################## // HandlerSet Functionality // public: static const Receiver::MessageHandlerSet NullSet; Receiver::Handler Find(Receiver::MessageID message) const { Check(this); Verify(message > 0); return (message<=entryCount) ? messageHandlers[message-1].entryHandler : Receiver::NullHandler; } const Receiver::HandlerEntry* Find(const char* name) const; const char * GetName(Receiver::MessageID message) const { Check(this); return (message<=entryCount) ? messageHandlers[message-1].entryName : NULL; } protected: Receiver::HandlerEntry* messageHandlers; //########################################################################## // Test Support // public: static Logical TestClass(); }; //########################################################################## //########################## Derivation ############################## //########################################################################## class Derivation: public Node { friend class Receiver; //########################################################################## // Construction and Destruction // public: Derivation(char *who); Derivation(Derivation *parent,char *who); char *className; //########################################################################## // Messagetap support // private: Derivation(Derivation& copy); ChainOf activeTaps; public: void AppendMessageTap(MessageTap* tap); Logical IsDescendedFrom(Derivation& parent); Logical IsDescendedFrom(const char* parent); //########################################################################## // Inheritance Registration Support // private: ChainOf classDerivations; void AppendDerivation(Derivation* child) {Check(this); classDerivations.Add(child);} //########################################################################## // Test Support // public: static Logical TestClass(); }; //########################################################################## //################### Receiver::SharedData ########################## //########################################################################## class Receiver__SharedData SIGNATURED { public: Receiver__SharedData( Derivation* derivation, Receiver::MessageHandlerSet &handler ): derivedClasses(derivation), activeMessageHandlers(&handler) { //activeMessageHandlers = &activeMessageHandlersInstance; } Derivation *derivedClasses; Receiver::MessageHandlerSet *activeMessageHandlers; Logical TestInstance() const; //private: // Receiver::MessageHandlerSet activeMessageHandlersInstance; }; inline Receiver::SharedData* Receiver::GetSharedData() const {Check(this); return Cast_Object(SharedData*,sharedData);} inline Derivation* Receiver::GetDerivation() const {Check(this); return GetSharedData()->derivedClasses;} inline Logical Receiver::IsDerivedFrom(Derivation& parent) const {return sharedData->derivedClasses->IsDescendedFrom(parent);} inline Logical Receiver::IsDerivedFrom(const char* parent) const {Check(this); return GetDerivation()->IsDescendedFrom(parent);} inline MessageTap* Receiver::MakeMessageTap( Derivation *derivation, ScanCallback callback ) {Check(this); return new MessageTap(derivation, this, callback);} inline MessageTap* Receiver::MakeMessageTap( Derivation *derivation, ScanCallback callback, Receiver::MessageID matching_message, Receiver *match_receiver ) { Check(this); return new MessageTap( derivation, this, callback, matching_message, match_receiver ); }