//===========================================================================// // File: receiver.cc // // Project: MUNGA Brick: Dynamic Dispatch // // Contents: Implementation Details of Dynamic Dispatch Processing // //---------------------------------------------------------------------------// // 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/05/94 JMA Made compatible with GNU C++ // // 11/30/94 JMA Adapted to new style conventions // // 12/01/94 JMA Made compatible with SGI CC // // 12/04/94 JMA Moved Message under Receiver, merged with message.hh // //---------------------------------------------------------------------------// // Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // // PROPRIETARY AND CONFIDENTIAL // //===========================================================================// #include "AdeptHeaders.hpp" //############################################################################# //############################# Receiver ################################ //############################################################################# const Receiver::MessageHandler Receiver::NullMessageHandler=NULL; const Receiver::MessageEntry Receiver::MessageEntries[]= { MESSAGE_ENTRY(Receiver, Default) }; Receiver::ClassData* Receiver::DefaultData = NULL; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Receiver::InitializeClass() { Verify(!DefaultData); DefaultData = new ClassData( ReceiverClassID, "Adept::Receiver", Plug::DefaultData, ELEMENTS(MessageEntries), MessageEntries ); Register_Object(DefaultData); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Receiver::TerminateClass() { Unregister_Object(DefaultData); delete DefaultData; DefaultData = NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Receiver::Receiver(ClassData *class_data): Plug(class_data) { } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Receiver::DefaultMessageHandler(const Message* message) { SPEW((0, "Default Handler activated on message ID %d", message->messageID)); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Receiver::Receive(const Message *what) { Check_Object(this); Check_Object(what); // //-------------------------------------------------------------------------- // Now, see if the receiver can handle this type of message, and if so, send // the message to the returned method handler //-------------------------------------------------------------------------- // ClassData *class_data = GetClassData(); Check_Object(class_data); MessageHandler handler = class_data->GetMessageHandler(what->messageID); Verify(handler != Receiver::NullMessageHandler); #if defined(_DEBUG) && 0 // jcem - for MR test { char Buffer[128]; sprintf(Buffer, "Receiver:: %s\n", class_data->messageHandlers[what->messageID-1].messageName); OutputDebugString(Buffer); } #endif // _DEBUG && ... (this->*handler)(what); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Receiver::Receive(Event *event) { Receive(event->messageToSend); Unregister_Object(event); delete event; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Receiver::FlushEvents(int) // max_priority doesn't work yet!!!! { Check_Object(this); STOP(("Not implemented")); #if 0 PlugIteratorOf i(this); Event *event; while ((event = i.ReadAndNext()) != NULL) { if (event->GetClassID() == EventClassID) { Unregister_Object(event); delete event; } } #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Receiver::FlushMatchingEvents( Receiver::MessageID target_message, int // max_priority doesn't work yet!!!! ) { Check_Object(this); STOP(("Not implemented")); #if 0 PlugIteratorOf i(this); Event* event; while ((event = i.ReadAndNext()) != NULL) { if ( event->GetClassID() == EventClassID && ( target_message == Receiver::AnyMessageID || event->messageToSend->messageID == target_message ) ) { Unregister_Object(event); delete event; } } #endif } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Receiver::TestInstance() { Verify(IsDerivedFrom(DefaultData)); } //############################################################################# //############################# ClassData ############################## //############################################################################# //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Receiver__ClassData::Receiver__ClassData( RegisteredClass::ClassID class_id, const char *class_name, Plug::ClassData *parent, Receiver::MessageID count, const Receiver::MessageEntry *handler_table ): Plug__ClassData(class_id, class_name, parent) { Check_Pointer(this); // //---------------------------- // Look for our parent's table //---------------------------- // Receiver__ClassData *inheritance; if (class_id != ReceiverClassID) { inheritance = Cast_Pointer(Receiver__ClassData*, parent); Check_Object(inheritance); } else { Verify(parent->GetClassID() == PlugClassID); inheritance = NULL; } // //--------------------------------------------------------------- // If we have not supplied a message table, use our parents table //--------------------------------------------------------------- // if (count == 0 && inheritance != NULL) { Check_Object(inheritance); deleteMessages = false; messageHandlers = inheritance->messageHandlers; messageCount = inheritance->messageCount; return; } // //--------------------------------- // We will have to make a new table //--------------------------------- // deleteMessages = true; Check_Pointer(handler_table); Verify(count > 0); // //------------------------------------------------------- // Find out the highest message type we have to deal with //------------------------------------------------------- // messageCount = 0; Receiver::MessageID i; for (i=0; i messageCount) { messageCount = handler_table[i].messageID; } } // //-------------------------------------------------- // Adjust the table size to include our parent stuff //-------------------------------------------------- // if (inheritance) { Verify(messageCount <= inheritance->messageCount + count); if (messageCount < inheritance->messageCount) { messageCount = inheritance->messageCount; } #if defined(_ARMOR) else if (messageCount > inheritance->messageCount) { i = inheritance->messageCount+1; goto Check_Table; } #endif } // //----------------------------------------------- // Make sure that there are no holes in the table //----------------------------------------------- // else { Verify(messageCount == count); #if defined(_ARMOR) i = 1; Check_Table: while (i <= messageCount) { int j; for (j=0; j count); #endif } // //----------------------------------------------------------------------- // Allocate the memory for the new handler set, and copy the inherited // handlers to the new table. We are guaranteed to have enough space for // the inherited table //----------------------------------------------------------------------- // messageHandlers = new Receiver::MessageEntry[messageCount]; Register_Pointer(messageHandlers); i = 0; if (inheritance) { for (; imessageCount; ++i) { messageHandlers[i] = inheritance->messageHandlers[i]; } } // //---------------------------------------------------------------------- // Step through the new table supplied, placing each handler in the slot // determined by the message type //---------------------------------------------------------------------- // for (i=0; i= 0 && index < messageCount); messageHandlers[index] = handler_table[i]; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Receiver__ClassData::~Receiver__ClassData() { if (deleteMessages) { Unregister_Pointer(messageHandlers); delete[] messageHandlers; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // size_t Receiver__ClassData::WriteClassBlock( MemoryStream* stream, bool write_it ) { Check_Object(this); int size = 0; // //---------------------------------------------------------------- // If we are just finding out the size of the class, figure it out //---------------------------------------------------------------- // if (!write_it) { size += 2*sizeof(int); size += strlen(GetClassName())+1; int messages = GetMessageCount(); for (int i=1; i<=messages; ++i) { const Receiver::MessageEntry *entry = GetMessageEntry(i); Check_Pointer(entry); const char* name = entry->messageName; Check_Pointer(name); size += strlen(name) + 1; } size = (size+3)&~3; } // //------------------------ // Otherwise, write it out //------------------------ // else { int messages = GetMessageCount(); *stream << GetClassID() << messages; size_t str_len = strlen(GetClassName()) + 1; stream->WriteBytes(className, str_len); size = str_len; for (int i=1; i<=messages; ++i) { const Receiver::MessageEntry *entry = GetMessageEntry(i); Check_Pointer(entry); const char* name = entry->messageName; Check_Pointer(name); str_len = strlen(name) + 1; stream->WriteBytes(name, str_len); size += str_len; } while (size&3) { *stream << '\0'; ++size; } size = 0; } // //--------------------------------------------------------------------- // Now call all of our derived classes and add their sizes to the total //--------------------------------------------------------------------- // RegisteredClass__ClassData *class_data = firstChildClass; while (class_data) { Receiver__ClassData *receiver_class = Cast_Pointer(Receiver__ClassData*, class_data); Check_Object(receiver_class); size += receiver_class->WriteClassBlock(stream, write_it); class_data = receiver_class->nextSiblingClass; } return size; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // const Receiver::MessageEntry* Receiver__ClassData::FindMessageEntry(const char* name) { Check_Object(this); Check_Pointer(name); for (int i=0; i