//===========================================================================// // File: receiver.hpp // // Project: MUNGA Brick: Dynamic Dispatch // // Contents: Dynamic Dispatch Interface // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 10/19/94 JMA Initial coding. // // 10/28/94 JMA Made compatible with SGI CC // // 11/03/94 ECH Made compatible with BC4.0 // // 11/04/94 JMA Made compatible with GNU C++ // // 11/04/94 ECH Added null handler set // // 11/29/94 JMA Changed ClassIdentity to ClassID // // 11/30/94 JMA Adapted to new style conventions // // 12/04/94 JMA Moved Message under Receiver, merged with message.hpp // // 12/06/94 JMA Made DefaultData publicly visible // //---------------------------------------------------------------------------// // Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved // // PROPRIETARY AND CONFIDENTIAL // //===========================================================================// #pragma once #include "Adept.hpp" #include "Resource.hpp" namespace Adept { class Receiver__MessageEntry; class Event; class Receiver__ClassData; class Receiver__Message; //########################################################################## //########################## 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 Stuff::Plug { public: static void InitializeClass(); static void TerminateClass(); typedef Receiver__ClassData ClassData; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Construction/Destruction // protected: Receiver(ClassData *class_data); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class data support // public: ClassData* GetClassData(); static ClassData* DefaultData; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Messaging Support // public: typedef Receiver__MessageEntry MessageEntry; typedef void (Receiver::*MessageHandler)(const Receiver__Message*); typedef int MessageID; typedef Receiver__Message Message; enum { AnyMessageID=0, DefaultMessageID, NextMessageID }; static const MessageHandler NullMessageHandler; void Receive(const Message *What); virtual void Dispatch(const Message *What) {Receive(What);} void DefaultMessageHandler(const Message*); const MessageEntry* GetMessageEntry(MessageID message); protected: static const MessageEntry MessageEntries[]; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Message Tap Support // public: typedef void (Receiver::*ScanCallback)( const Receiver::Message *message, Receiver *receiver ); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Event Support // public: virtual void Receive(Event *event); void FlushEvents(int max_priority=-1); void FlushMatchingEvents( MessageID target_message, int max_priority=-1 ); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Test Support // public: static bool TestClass(); void TestInstance(); }; //########################################################################## //###################### Receiver::Message ########################### //########################################################################## class Receiver__Message { public: size_t messageLength; Receiver::MessageID messageID; int messagePriority; enum { ReliableBit, NextBit }; enum { DefaultFlags = 0, ReliableFlag = 1 << ReliableBit }; int messageFlags; Receiver__Message( Receiver::MessageID id, size_t message_length, int priority, int flags ): messageID(id), messageLength(message_length), messagePriority(priority), messageFlags(flags) {} void TestInstance() const {} }; //########################################################################## //#################### ReceiverDataMessageOf ######################### //########################################################################## template class ReceiverDataMessageOf: public Receiver__Message { public: T dataContents; ReceiverDataMessageOf( Receiver::MessageID id, size_t message_length, int priority, int flags, const T& data ): Receiver__Message(id, message_length, priority, flags), dataContents(data) {} }; //########################################################################## //################### Receiver::MessageEntry ######################### //########################################################################## class Receiver__MessageEntry { public: int messageID; const char* messageName; Receiver::MessageHandler messageHandler; void TestInstance() const {} }; #define MESSAGE_ENTRY(c,m)\ {\ c::m##MessageID,\ #m,\ (Receiver::MessageHandler)\ (void (c::*)(const Receiver__Message*))(\ &c::m##MessageHandler\ )\ } //########################################################################## //#################### Receiver::ClassData ########################### //########################################################################## class Receiver__ClassData: public Stuff::Plug__ClassData { friend class Receiver; public: Receiver__ClassData( Stuff::RegisteredClass::ClassID class_id, const char *class_name, Stuff::Plug::ClassData *parent, Receiver::MessageID count, const Receiver::MessageEntry *handler_table ); ~Receiver__ClassData(); size_t WriteClassBlock( Stuff::MemoryStream *stream, bool actual_write ); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Message support // public: const Receiver::MessageEntry* FindMessageEntry(const char* name); const Receiver::MessageEntry* GetMessageEntry(Receiver::MessageID message) { Check_Object(this); Verify(message > 0); return (message<=messageCount) ? &messageHandlers[message-1] : NULL; } Receiver::MessageHandler GetMessageHandler(Receiver::MessageID message) { Check_Object(this); Verify(message > 0); return (message<=messageCount) ? messageHandlers[message-1].messageHandler : Receiver::NullMessageHandler; } int GetMessageCount() {Check_Object(this); return messageCount;} protected: int messageCount; Receiver__MessageEntry *messageHandlers; bool deleteMessages; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Test support // public: void TestInstance(); }; inline Receiver__ClassData* Receiver::GetClassData() {return Cast_Pointer(ClassData*, classData);} inline const Receiver::MessageEntry* Receiver::GetMessageEntry(Receiver::MessageID message) { Check_Object(this); return GetClassData()->GetMessageEntry(message); } }