//========================================================================= // CLISTENER.CC - part of // // OMNeT++/OMNEST // Discrete System Simulation in C++ // //========================================================================= /*--------------------------------------------------------------* Copyright (C) 1992-2017 Andras Varga Copyright (C) 2006-2017 OpenSim Ltd. This file is distributed WITHOUT ANY WARRANTY. See the file `license' for details on this and other legal matters. *--------------------------------------------------------------*/ #include "omnetpp/clistener.h" #include "omnetpp/ccomponent.h" #include "omnetpp/cmodule.h" #include "omnetpp/cchannel.h" #include "omnetpp/csimulation.h" namespace omnetpp { struct Subscription { cComponent *component; simsignal_t signalID; }; typedef std::vector SubscriptionList; static void findListenerOccurences(cComponent *component, cIListener *listener, SubscriptionList& result) { std::vector signals = component->getLocalListenedSignals(); for (int signalID : signals) { if (component->isSubscribed(signalID, listener)) { result.push_back(Subscription()); result.back().component = component; result.back().signalID = signalID; } } if (component->isModule()) { cModule *module = (cModule *)component; for (cModule::SubmoduleIterator it(module); !it.end(); ++it) findListenerOccurences(*it, listener, result); for (cModule::ChannelIterator it(module); !it.end(); ++it) findListenerOccurences(*it, listener, result); } } //--- cIListener::cIListener() { subscribeCount = 0; } cIListener::~cIListener() { if (subscribeCount) { // note: throwing an exception would is risky here: it would typically // cause other exceptions, and eventually crash if (subscribeCount < 0) { getEnvir()->printfmsg( "cListener destructor: internal error: negative subscription " "count (%d) in listener at address %p", subscribeCount, this); return; } // subscribecount > 0: getEnvir()->printfmsg( "cListener destructor: listener at address %p is still added to " "%d listener list(s). This will likely result in a crash: " "Listeners must be fully unsubscribed before deletion. " "Trying to determine components where this listener is subscribed...", this, subscribeCount); // print components and signals where this listener is subscribed std::stringstream out; SubscriptionList subscriptionList; findListenerOccurences(getSimulation()->getSystemModule(), this, subscriptionList); for (auto & subscription : subscriptionList) { out << "- signal \"" << cComponent::getSignalName(subscription.signalID) << "\" (id=" << subscription.signalID << ") "; out << "at (" << subscription.component->getClassName() << ")" << subscription.component->getFullPath() << "\n"; } getEnvir()->printfmsg("Subscriptions for listener at address %p:\n%s", this, out.str().c_str()); } } //--- void cListener::unsupportedType(simsignal_t signalID, const char *dataType) { const char *signalName = cComponent::getSignalName(signalID); throw cRuntimeError("%s: Unsupported signal data type %s for signal %s (id=%d)", opp_typename(typeid(*this)), dataType, signalName, (int)signalID); } #ifndef WITH_OMNETPP4x_LISTENER_SUPPORT void cListener::receiveSignal(cComponent *, simsignal_t signalID, bool, cObject *) { unsupportedType(signalID, "bool"); } void cListener::receiveSignal(cComponent *, simsignal_t signalID, long, cObject *) { unsupportedType(signalID, "long"); } void cListener::receiveSignal(cComponent *, simsignal_t signalID, unsigned long, cObject *) { unsupportedType(signalID, "unsigned long"); } void cListener::receiveSignal(cComponent *, simsignal_t signalID, double, cObject *) { unsupportedType(signalID, "double"); } void cListener::receiveSignal(cComponent *, simsignal_t signalID, const SimTime&, cObject *) { unsupportedType(signalID, "simtime_t"); } void cListener::receiveSignal(cComponent *, simsignal_t signalID, const char *, cObject *) { unsupportedType(signalID, "const char *"); } void cListener::receiveSignal(cComponent *, simsignal_t signalID, cObject *, cObject *) { unsupportedType(signalID, "cObject *"); } #else // WITH_OMNETPP4x_LISTENER_SUPPORT // Support for OMNeT++ 4.x listeners: #define LISTENER(TYPE) \ void cListener::receiveSignal(cComponent *, simsignal_t signalID, TYPE) { unsupportedType(signalID, #TYPE); } \ void cListener::receiveSignal(cComponent *source, simsignal_t signalID, TYPE d, cObject *) { receiveSignal(source, signalID, d); } LISTENER(bool); LISTENER(long); LISTENER(unsigned long); LISTENER(double); LISTENER(const SimTime&); LISTENER(const char *); LISTENER(cObject *); #undef LISTENER #endif // WITH_OMNETPP4x_LISTENER_SUPPORT } // namespace omnetpp