bool MessageDispatcher::dispatch(Message& msg) { #ifdef XDEBUG Debugger debug("MessageDispatcher::dispatch","(%p) (\"%s\")",&msg,msg.c_str()); #endif #ifndef NDEBUG u_int64_t t = Time::now(); #endif bool retv = false; ObjList *l = &m_handlers; Lock mylock(this); for (; l; l=l->next()) { MessageHandler *h = static_cast<MessageHandler*>(l->get()); if (h && (h->null() || *h == msg)) { if (h->filter() && (*(h->filter()) != msg.getValue(h->filter()->name()))) continue; unsigned int c = m_changes; unsigned int p = h->priority(); if (trackParam() && h->trackName()) { NamedString* tracked = msg.getParam(trackParam()); if (tracked) tracked->append(h->trackName(),","); else msg.addParam(trackParam(),h->trackName()); } // mark handler as unsafe to destroy / uninstall h->m_unsafe++; mylock.drop(); #ifdef DEBUG u_int64_t tm = Time::now(); #endif retv = h->receivedInternal(msg) || retv; #ifdef DEBUG tm = Time::now() - tm; if (m_warnTime && (tm > m_warnTime)) Debug(DebugInfo,"Message '%s' [%p] passed through %p in " FMT64U " usec", msg.c_str(),&msg,h,tm); #endif if (retv && !msg.broadcast()) break; mylock.acquire(this); if (c == m_changes) continue; // the handler list has changed - find again NDebug(DebugAll,"Rescanning handler list for '%s' [%p] at priority %u", msg.c_str(),&msg,p); ObjList* l2 = &m_handlers; for (l = l2; l; l=l->next()) { MessageHandler *mh = static_cast<MessageHandler*>(l->get()); if (!mh) continue; if (mh == h) // exact match - silently continue where we left break; // gone past last handler priority - exit with last handler if ((mh->priority() > p) || ((mh->priority() == p) && (mh > h))) { Debug(DebugAll,"Handler list for '%s' [%p] changed, skipping from %p (%u) to %p (%u)", msg.c_str(),&msg,h,p,mh,mh->priority()); // l will advance in the outer for loop so use previous l = l2; break; } l2 = l; } if (!l) break; } } mylock.drop(); msg.dispatched(retv); #ifndef NDEBUG t = Time::now() - t; if (m_warnTime && (t > m_warnTime)) { unsigned n = msg.length(); String p; for (unsigned i = 0; i < n; i++) { NamedString *s = msg.getParam(i); if (s) p << "\n ['" << s->name() << "']='" << *s << "'"; } Debug("Performance",DebugMild,"Message %p '%s' retval '%s' returned %s in " FMT64U " usec%s", &msg,msg.c_str(),msg.retValue().c_str(),retv ? "true" : "false",t,p.safe()); } #endif l = &m_hooks; for (; l; l=l->next()) { MessagePostHook *h = static_cast<MessagePostHook*>(l->get()); if (h) h->dispatched(msg,retv); } return retv; }
bool MessageDispatcher::dispatch(Message& msg) { #ifdef XDEBUG Debugger debug("MessageDispatcher::dispatch","(%p) (\"%s\")",&msg,msg.c_str()); #endif #ifndef NDEBUG u_int64_t t = Time::now(); #endif bool retv = false; ObjList *l = &m_handlers; m_mutex.lock(); for (; l; l=l->next()) { MessageHandler *h = static_cast<MessageHandler*>(l->get()); if (h && (h->null() || *h == msg)) { if (h->filter() && (*(h->filter()) != msg.getValue(h->filter()->name()))) continue; unsigned int c = m_changes; unsigned int p = h->priority(); m_mutex.unlock(); #ifdef DEBUG u_int64_t tm = Time::now(); #endif retv = h->received(msg); #ifdef DEBUG tm = Time::now() - tm; if (m_warnTime && (tm > m_warnTime)) Debug(DebugInfo,"Message '%s' [%p] passed through %p in " FMT64U " usec", msg.c_str(),&msg,h,tm); #endif if (retv) break; m_mutex.lock(); if (c == m_changes) continue; // the handler list has changed - find again NDebug(DebugAll,"Rescanning handler list for '%s' [%p] at priority %u", msg.c_str(),&msg,p); for (l = &m_handlers; l; l=l->next()) { MessageHandler *mh = static_cast<MessageHandler*>(l->get()); if (!mh) continue; if (mh == h) // exact match - silently continue where we left break; // gone past last handler priority - exit with last handler if ((mh->priority() > p) || ((mh->priority() == p) && (mh > h))) { Debug(DebugAll,"Handler list for '%s' [%p] changed, skipping from %p (%u) to %p (%u)", msg.c_str(),&msg,h,p,mh,mh->priority()); break; } } } } if (!l) m_mutex.unlock(); msg.dispatched(retv); #ifndef NDEBUG t = Time::now() - t; if (m_warnTime && (t > m_warnTime)) { unsigned n = msg.length(); String p; for (unsigned i = 0; i < n; i++) { NamedString *s = msg.getParam(i); if (s) p << "\n ['" << s->name() << "']='" << *s << "'"; } Debug("Performance",DebugMild,"Message %p '%s' retval '%s' returned %s in " FMT64U " usec%s", &msg,msg.c_str(),msg.retValue().c_str(),retv ? "true" : "false",t,p.safe()); } #endif l = &m_hooks; for (; l; l=l->next()) { MessagePostHook *h = static_cast<MessagePostHook*>(l->get()); if (h) h->dispatched(msg,retv); } return retv; }