Пример #1
0
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;
}