Added a broadcast flag to class Message so it can continue dispatching even if one of the handlers returned true.

Use the broadcast flag in the messages emitted by the engine.


git-svn-id: http://voip.null.ro/svn/yate@3384 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
paulc 2010-06-16 11:42:52 +00:00
parent 3878b24178
commit 0cdbe20050
3 changed files with 50 additions and 21 deletions

View File

@ -1057,8 +1057,7 @@ int Engine::run()
::signal(SIGINT,sighandler);
::signal(SIGTERM,sighandler);
Debug(DebugAll,"Engine dispatching start message");
if (dispatch("engine.start"))
Debug(DebugGoOn,"Message engine.start was unexpectedly handled!");
dispatch("engine.start",true);
setStatus(SERVICE_RUNNING);
long corr = 0;
#ifndef _WINDOWS
@ -1071,7 +1070,7 @@ int Engine::run()
Output("Yate%s engine is initialized and starting up%s%s",
clientMode() ? " client" : "",s_node.null() ? "" : " on " ,s_node.safe());
int stops = MAX_STOP;
while (s_haltcode == -1 || ((--stops >= 0) && dispatch("engine.stop"))) {
while (s_haltcode == -1 || ((--stops >= 0) && dispatch("engine.stop",true))) {
if (s_cmds) {
Output("Executing initial commands");
for (ObjList* c = s_cmds->skipNull(); c; c=c->skipNext()) {
@ -1137,7 +1136,7 @@ int Engine::run()
t += 1000000;
XDebug(DebugAll,"Sleeping for %ld",t);
Thread::usleep(t);
Message *m = new Message("engine.timer");
Message* m = new Message("engine.timer",0,true);
m->addParam("time",String((int)m->msgTime().sec()));
if (nodeName())
m->addParam("nodename",nodeName());
@ -1157,8 +1156,7 @@ int Engine::run()
Output("Yate engine is shutting down with code %d",s_haltcode);
setStatus(SERVICE_STOP_PENDING);
::signal(SIGINT,SIG_DFL);
if (dispatch("engine.halt"))
Debug(DebugGoOn,"Message engine.halt was unexpectedly handled!");
dispatch("engine.halt",true);
checkPoint();
Thread::msleep(200);
m_dispatcher.dequeue();
@ -1359,8 +1357,7 @@ void Engine::initPlugins()
if (exiting())
return;
Output("Initializing plugins");
if (dispatch("engine.init"))
Debug(DebugGoOn,"Message engine.init was unexpectedly handled!");
dispatch("engine.init",true);
ObjList *l = plugins.skipNull();
for (; l; l = l->skipNext()) {
Plugin *p = static_cast<Plugin *>(l->get());
@ -1449,11 +1446,11 @@ bool Engine::dispatch(Message& msg)
return s_self ? s_self->m_dispatcher.dispatch(msg) : false;
}
bool Engine::dispatch(const char* name)
bool Engine::dispatch(const char* name, bool broadcast)
{
if (!(s_self && name && *name))
return false;
Message msg(name);
Message msg(name,0,broadcast);
if (nodeName())
msg.addParam("nodename",nodeName());
return s_self->m_dispatcher.dispatch(msg);

View File

@ -25,20 +25,31 @@
using namespace TelEngine;
Message::Message(const char* name, const char* retval)
: NamedList(name), m_return(retval), m_data(0), m_notify(false)
Message::Message(const char* name, const char* retval, bool broadcast)
: NamedList(name),
m_return(retval), m_data(0), m_notify(false), m_broadcast(broadcast)
{
XDebug(DebugAll,"Message::Message(\"%s\",\"%s\") [%p]",name,retval,this);
XDebug(DebugAll,"Message::Message(\"%s\",\"%s\",%s) [%p]",
name,retval,String::boolText(broadcast),this);
}
Message::Message(const Message& original)
: NamedList(original),
m_return(original.retValue()), m_time(original.msgTime()),
m_data(0), m_notify(false)
m_data(0), m_notify(false), m_broadcast(original.broadcast())
{
XDebug(DebugAll,"Message::Message(&%p) [%p]",&original,this);
}
Message::Message(const Message& original, bool broadcast)
: NamedList(original),
m_return(original.retValue()), m_time(original.msgTime()),
m_data(0), m_notify(false), m_broadcast(broadcast)
{
XDebug(DebugAll,"Message::Message(&%p,%s) [%p]",
&original,String::boolText(broadcast),this);
}
Message::~Message()
{
XDebug(DebugAll,"Message::~Message() '%s' [%p]",c_str(),this);
@ -371,14 +382,14 @@ bool MessageDispatcher::dispatch(Message& msg)
#ifdef DEBUG
u_int64_t tm = Time::now();
#endif
retv = h->receivedInternal(msg);
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)
if (retv && !msg.broadcast())
break;
lock();
if (c == m_changes)

View File

@ -224,16 +224,25 @@ public:
*
* @param name Name of the message - must not be NULL or empty
* @param retval Default return value
* @param broadcast Broadcast flag, true if handling the mesage must not stop it
*/
explicit Message(const char* name, const char* retval = 0);
explicit Message(const char* name, const char* retval = 0, bool broadcast = false);
/**
* Copy constructor.
* Note that user data and notification are not copied.
* Note that user data and notification are not copied
* @param original Message we are copying from
*/
Message(const Message& original);
/**
* Copy constructor that can alter the broadcast flag.
* Note that user data and notification are not copied
* @param original Message we are copying from
* @param broadcast Broadcast flag, true if handling the mesage must not stop it
*/
Message(const Message& original, bool broadcast);
/**
* Destruct the message and dereferences any user data
*/
@ -292,6 +301,13 @@ public:
inline void setNotify(bool notify = true)
{ m_notify = notify; }
/**
* Retrieve the broadcast flag
* @return True if the message is a broadcast (handling does not stop it)
*/
inline bool broadcast() const
{ return m_broadcast; }
/**
* Retrieve a reference to the creation time of the message.
* @return A reference to the @ref Time when the message was created
@ -364,6 +380,7 @@ private:
Time m_time;
RefObject* m_data;
bool m_notify;
bool m_broadcast;
void commonEncode(String& str) const;
int commonDecode(const char* str, int offs);
};
@ -582,6 +599,8 @@ public:
* Synchronously dispatch a message to the installed handlers.
* Handlers matching the message name and filter parameter are called in
* their installed order (based on priority) until one returns true.
* If the message has the broadcast flag set all matching handlers are
* called and the return value is true if any handler returned true.
* Note that in some cases when a handler is removed from the list
* other handlers with equal priority may be called twice.
* @param msg The message to dispatch
@ -997,10 +1016,11 @@ public:
* Convenience function.
* Enqueue a new parameterless message in the message queue
* @param name Name of the parameterless message to put in queue
* @param broadcast Broadcast flag, true if handling the mesage must not stop it
* @return True if enqueued, false on error (already queued)
*/
inline static bool enqueue(const char* name)
{ return (name && *name) ? enqueue(new Message(name)) : false; }
inline static bool enqueue(const char* name, bool broadcast = false)
{ return name && *name && enqueue(new Message(name,0,broadcast)); }
/**
* Synchronously dispatch a message to the registered handlers
@ -1020,9 +1040,10 @@ public:
* Convenience function.
* Dispatch a parameterless message to the registered handlers
* @param name The name of the message to create and dispatch
* @param broadcast Broadcast flag, true if handling the mesage must not stop it
* @return True if one handler accepted it, false if all ignored
*/
static bool dispatch(const char* name);
static bool dispatch(const char* name, bool broadcast = false);
/**
* Install or remove a hook to catch messages after being dispatched