#include "munga.h" #pragma hdrstop #include "receiver.h" #include "event.h" //############################################################################# //############################# Receiver ################################ //############################################################################# const Receiver::Handler Receiver::NullHandler=NULL; Receiver::SharedData Receiver::DefaultData( Receiver::GetClassDerivations(), Receiver::GetMessageHandlers() ); Derivation* Receiver::GetClassDerivations() { static Derivation classDerivations("Receiver"); return &classDerivations; } const Receiver::HandlerEntry Receiver::MessageHandlerEntries[]= { { Receiver::WatcherChangedMessageID, "WatcherChanged", (Receiver::Handler)&Receiver::DefaultMessageHandler }, { Receiver::LoadResourceFinishedMessageID, "LoadResourceFinished", (Receiver::Handler)&Receiver::DefaultMessageHandler } }; Receiver::MessageHandlerSet& Receiver::GetMessageHandlers() { static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(Receiver::MessageHandlerEntries), Receiver::MessageHandlerEntries); return messageHandlers; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // #if defined(USE_SIGNATURE) int Is_Signature_Bad(const volatile Receiver__Message *) { return False; } #endif //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void #if DEBUG_LEVEL>0 Receiver::DefaultMessageHandler(Message* message) #else Receiver::DefaultMessageHandler(Message*) #endif { Tell( "Default Handler activated on message ID " << message->messageID << endl ); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Receiver::Receive(Message *what) { // //------------------------------------------------------------------------- // Service the message taps by creating an iterator to step through all the // MessageTaps registered with the Derivation object for the receiver's // class. Each tap will do whatever it thinks best about this receiver // having received this message //------------------------------------------------------------------------- // Check(this); Check_Pointer(what); ChainIteratorOf i(GetDerivation()->activeTaps); MessageTap *tap; while ((tap = i.ReadAndNext()) != NULL) { tap->Scan(this,what); } // //-------------------------------------------------------------------------- // Now, see if the receiver can handle this type of message, and if so, send // the message to the returned method handler //-------------------------------------------------------------------------- // Receiver::SharedData *sharedData = GetSharedData(); Handler handler = sharedData->activeMessageHandlers->Find(what->messageID); // MP DIAGNOSTIC (task #47): for a TakeDamage (msgID 21), report whether a // handler is found on this receiver (the cross-pod delivery endpoint). if (what->messageID == 21 && getenv("BT_MP_NET")) DEBUG_STREAM << "[mp-recv2] Receive TakeDamage this=" << (void*)this << " handler=" << (handler != Receiver::NullHandler ? "FOUND" : "NULL") << "\n" << std::flush; if (handler != Receiver::NullHandler) { (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(this); PlugIteratorOf i(this); Event *event; while ((event = i.ReadAndNext()) != NULL) { if (event->GetClassID() == EventClassID) { Unregister_Object(event); delete event; } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Receiver::FlushMatchingEvents( Receiver::MessageID target_message, int // max_priority doesn't work yet!!!! ) { Check(this); 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; } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Receiver::ProcessDeferredQueue() { // //------------------------------------------------ // Find a delay queue, and return if there is none //------------------------------------------------ // Check(this); PlugIteratorOf i(this); DeferredEventQueue *deferred_queue; while ((deferred_queue = i.ReadAndNext()) != NULL) { if (deferred_queue->GetClassID() == DeferredEventQueueClassID) { break; } } if (!deferred_queue) { return; } // //-------------------------------------------------------------- // Now, tell the queue to process all its events, then delete it //-------------------------------------------------------------- // deferred_queue->ProcessAllEvents(); Unregister_Object(deferred_queue); delete deferred_queue; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical Receiver::TestInstance() const { return IsDerivedFrom(*GetClassDerivations()); } //############################################################################# //######################### Receiver::Message ########################### //############################################################################# //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical Receiver::Message::TestInstance() const { return True; } //############################################################################# //######################### Receiver::DynamicMessage ########################## //############################################################################# //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Receiver__DynamicMessage::Receiver__DynamicMessage( Receiver::MessageID message_ID, size_t message_size ) { Receiver::Message new_message(message_ID, message_size); WriteBytes(&new_message, message_size); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MemoryStream& Receiver::DynamicMessage::WriteBytes( const void *ptr, size_t number_of_bytes ) { DynamicMemoryStream::WriteBytes(ptr, number_of_bytes); Receiver::Message *message = GetMessagePointer(); size_t new_size = GetBytesUsed(); message->messageLength = new_size; return *this; } //############################################################################# //############################ MessageTap ############################### //############################################################################# MemoryBlock *MessageTap::GetAllocatedMemory() { static MemoryBlock allocatedMemory(sizeof(MessageTap), 30, 30, "Message Taps"); return &allocatedMemory; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MessageTap::MessageTap( Derivation *derivation, Receiver *client, Receiver::ScanCallback call_back ): Plug(MessageTapClassID) { // //--------------------------- // Initialize the message tap //--------------------------- // Check(client); clientReceiver = client; scanCallback = call_back; matchingReceiver = NULL; matchingMessageID = Receiver::AnyMessageID; // //-------------------------------------------- // Hook the tap up to the specified derivation //-------------------------------------------- // Check(derivation); derivation->AppendMessageTap(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MessageTap::MessageTap( Derivation *derivation, Receiver *client, Receiver::ScanCallback call_back, Receiver::MessageID messageID, Receiver *receiver ): Plug(MessageTapClassID) { // //--------------------------- // Initialize the message tap //--------------------------- // Check(client); clientReceiver = client; scanCallback = call_back; matchingReceiver = receiver; matchingMessageID = messageID; // //-------------------------------------------- // Hook the tap up to the specified derivation //-------------------------------------------- // Check(derivation); derivation->AppendMessageTap(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MessageTap::Scan( Receiver *receiver, Receiver::Message *message ) { Check(this); Check(message); if ( (!matchingReceiver || matchingReceiver == receiver) && ( matchingMessageID == Receiver::AnyMessageID || matchingMessageID == message->messageID ) ) { (clientReceiver->*scanCallback)(message,receiver); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical MessageTap::TestInstance() const { return True; } //############################################################################# //##################### Receiver::InheritanceSet ######################## //############################################################################# //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical Receiver::InheritanceSet::TestInstance() const { return True; } //############################################################################# //#################### Receiver::MessageHandlerSet ###################### //############################################################################# const Receiver::MessageHandlerSet Receiver::MessageHandlerSet::NullSet; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Receiver__MessageHandlerSet::~Receiver__MessageHandlerSet() { if (messageHandlers) { Unregister_Pointer(messageHandlers); delete[] messageHandlers; messageHandlers = NULL; } }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Receiver::MessageHandlerSet::Build( Receiver::MessageID count, const Receiver::HandlerEntry handler_table[], const Receiver::MessageHandlerSet *inheritance ) { // //------------------------------------------------------- // Find out the highest message type we have to deal with //------------------------------------------------------- // Check(this); Check_Pointer(handler_table); entryCount = 0; Receiver::MessageID i; for (i=0; i entryCount) { entryCount = handler_table[i].entryID; } } if (inheritance) { Check(inheritance); if (entryCount < inheritance->entryCount) { entryCount = inheritance->entryCount; } #if DEBUG_LEVEL>0 else if (entryCount > inheritance->entryCount) { i = inheritance->entryCount+1; goto Check_Table; } #endif } else { Verify(entryCount == count); #if DEBUG_LEVEL>0 i = 1; Check_Table: while (i <= entryCount) { 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::HandlerEntry[entryCount]; Check_Pointer(messageHandlers); Register_Pointer(messageHandlers); i = 0; if (inheritance) { for (; ientryCount; ++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 < entryCount); messageHandlers[index] = handler_table[i]; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // const Receiver::HandlerEntry* Receiver::MessageHandlerSet::Find(const char* name) const { Check(this); Check_Pointer(name); for (int i=0; iAppendDerivation(this); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Derivation::AppendMessageTap(MessageTap* tap) { Check(this); Check(tap); // //---------------------------------------------------------------------- // Add the tap to the taps chain, then step through all our derivations, // sending each of them this same method //---------------------------------------------------------------------- // activeTaps.Add(tap); ChainIteratorOf i(classDerivations); Derivation *derivation; while ((derivation = i.ReadAndNext()) != NULL) { derivation->AppendMessageTap(tap); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical Derivation::IsDescendedFrom(Derivation& parent) { Check(this); Check(&parent); // //------------------------------ // We are descended from ourself //------------------------------ // if (&parent == this) { return True; } // //---------------------------------------------------------------------- // Find our parent derivation, and ask him // sending each of them this same method //---------------------------------------------------------------------- // PlugIteratorOf i(this); Derivation *derivation; while ((derivation = i.ReadAndNext()) != NULL) { if (derivation->GetClassID() == DerivationClassID) { return derivation->IsDescendedFrom(parent); } } return False; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical Derivation::IsDescendedFrom(const char* parent) { Check(this); Check_Pointer(parent); // //------------------------------ // We are descended from ourself //------------------------------ // Check_Pointer(className); if (!strcmp(className, parent)) { return True; } // //---------------------------------------------------------------------- // Find our parent derivation, and ask him // sending each of them this same method //---------------------------------------------------------------------- // PlugIteratorOf i(this); Derivation *derivation; while ((derivation = i.ReadAndNext()) != NULL) { Check(derivation); if (derivation->GetClassID() == DerivationClassID) { return derivation->IsDescendedFrom(parent); } } return False; } //############################################################################# //###################### Receiver::SharedData ########################## //############################################################################# Logical Receiver::SharedData::TestInstance() const { return True; } #if defined(TEST_CLASS) # include "receiver.tcp" #endif