Пример #1
0
bool MessageDispatcher::install(MessageHandler* handler)
{
    DDebug(DebugAll,"MessageDispatcher::install(%p)",handler);
    if (!handler)
	return false;
    Lock lock(this);
    ObjList *l = m_handlers.find(handler);
    if (l)
	return false;
    unsigned p = handler->priority();
    int pos = 0;
    for (l=&m_handlers; l; l=l->next(),pos++) {
	MessageHandler *h = static_cast<MessageHandler *>(l->get());
	if (!h)
	    continue;
	if (h->priority() < p)
	    continue;
	if (h->priority() > p)
	    break;
	// at the same priority we sort them in pointer address order
	if (h > handler)
	    break;
    }
    m_changes++;
    if (l) {
	XDebug(DebugAll,"Inserting handler [%p] on place #%d",handler,pos);
	l->insert(handler);
    }
    else {
	XDebug(DebugAll,"Appending handler [%p] on place #%d",handler,pos);
	m_handlers.append(handler);
    }
    handler->m_dispatcher = this;
    if (handler->null())
	Debug(DebugInfo,"Registered broadcast message handler %p",handler);
    return true;
}
Пример #2
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;
    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;
}
Пример #3
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;
}