* applied the logic from BWindow::task_looper() to BLooper as well (messages to
invalid target handlers are dropped). * B_PREFERRED messages now go to the looper if there is no other preferred handler. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15088 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+36
-82
@@ -46,6 +46,7 @@ static BLocker sDebugPrintLocker("BLooper debug print");
|
|||||||
#include <PropertyInfo.h>
|
#include <PropertyInfo.h>
|
||||||
|
|
||||||
#include <LooperList.h>
|
#include <LooperList.h>
|
||||||
|
#include <MessagePrivate.h>
|
||||||
#include <ObjectLocker.h>
|
#include <ObjectLocker.h>
|
||||||
#include <TokenSpace.h>
|
#include <TokenSpace.h>
|
||||||
|
|
||||||
@@ -60,24 +61,6 @@ using BPrivate::BObjectLocker;
|
|||||||
using BPrivate::BLooperList;
|
using BPrivate::BLooperList;
|
||||||
|
|
||||||
port_id _get_looper_port_(const BLooper* looper);
|
port_id _get_looper_port_(const BLooper* looper);
|
||||||
#ifndef USING_MESSAGE4
|
|
||||||
bool _use_preferred_target_(BMessage* msg) { return msg->fPreferred; }
|
|
||||||
int32 _get_message_target_(BMessage* msg) { return msg->fTarget; }
|
|
||||||
#else
|
|
||||||
#include <MessagePrivate.h>
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
_use_preferred_target_(BMessage *message)
|
|
||||||
{
|
|
||||||
return BMessage::Private(message).UsePreferredTarget();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int32
|
|
||||||
_get_message_target_(BMessage *message)
|
|
||||||
{
|
|
||||||
return BMessage::Private(message).GetTarget();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32 BLooper::sLooperID = (uint32)B_ERROR;
|
uint32 BLooper::sLooperID = (uint32)B_ERROR;
|
||||||
team_id BLooper::sTeamID = (team_id)B_ERROR;
|
team_id BLooper::sTeamID = (team_id)B_ERROR;
|
||||||
@@ -1175,26 +1158,26 @@ BLooper::ReadMessageFromPort(bigtime_t tout)
|
|||||||
|
|
||||||
delete[] (int8*)msgbuffer;
|
delete[] (int8*)msgbuffer;
|
||||||
|
|
||||||
PRINT(("BLooper::ReadMessageFromPort() done: %p\n", bmsg));
|
PRINT(("BLooper::ReadMessageFromPort() done: %p\n", bmsg));
|
||||||
return bmsg;
|
return bmsg;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
BMessage* BLooper::ConvertToMessage(void* raw, int32 code)
|
|
||||||
|
BMessage*
|
||||||
|
BLooper::ConvertToMessage(void* raw, int32 code)
|
||||||
{
|
{
|
||||||
PRINT(("BLooper::ConvertToMessage()\n"));
|
PRINT(("BLooper::ConvertToMessage()\n"));
|
||||||
BMessage* bmsg = new BMessage(code);
|
BMessage* bmsg = new BMessage(code);
|
||||||
|
|
||||||
if (raw != NULL)
|
if (raw != NULL) {
|
||||||
{
|
if (bmsg->Unflatten((const char*)raw) != B_OK) {
|
||||||
if (bmsg->Unflatten((const char*)raw) != B_OK)
|
PRINT(("BLooper::ConvertToMessage(): unflattening message failed\n"));
|
||||||
{
|
|
||||||
PRINT(("BLooper::ConvertToMessage(): unflattening message failed\n"));
|
|
||||||
delete bmsg;
|
delete bmsg;
|
||||||
bmsg = NULL;
|
bmsg = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PRINT(("BLooper::ConvertToMessage(): %p\n", bmsg));
|
PRINT(("BLooper::ConvertToMessage(): %p\n", bmsg));
|
||||||
return bmsg;
|
return bmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1203,17 +1186,16 @@ void
|
|||||||
BLooper::task_looper()
|
BLooper::task_looper()
|
||||||
{
|
{
|
||||||
PRINT(("BLooper::task_looper()\n"));
|
PRINT(("BLooper::task_looper()\n"));
|
||||||
// Check that looper is locked (should be)
|
// Check that looper is locked (should be)
|
||||||
AssertLocked();
|
AssertLocked();
|
||||||
// Unlock the looper
|
// Unlock the looper
|
||||||
Unlock();
|
Unlock();
|
||||||
|
|
||||||
if (IsLocked())
|
if (IsLocked())
|
||||||
debugger("looper must not be locked!");
|
debugger("looper must not be locked!");
|
||||||
|
|
||||||
// loop: As long as we are not terminating.
|
// loop: As long as we are not terminating.
|
||||||
while (!fTerminating)
|
while (!fTerminating) {
|
||||||
{
|
|
||||||
PRINT(("LOOPER: outer loop\n"));
|
PRINT(("LOOPER: outer loop\n"));
|
||||||
// TODO: timeout determination algo
|
// TODO: timeout determination algo
|
||||||
// Read from message port (how do we determine what the timeout is?)
|
// Read from message port (how do we determine what the timeout is?)
|
||||||
@@ -1225,27 +1207,26 @@ BLooper::task_looper()
|
|||||||
if (msg)
|
if (msg)
|
||||||
_AddMessagePriv(msg);
|
_AddMessagePriv(msg);
|
||||||
|
|
||||||
// Get message count from port
|
// Get message count from port
|
||||||
int32 msgCount = port_count(fMsgPort);
|
int32 msgCount = port_count(fMsgPort);
|
||||||
for (int32 i = 0; i < msgCount; ++i) {
|
for (int32 i = 0; i < msgCount; ++i) {
|
||||||
// Read 'count' messages from port (so we will not block)
|
// Read 'count' messages from port (so we will not block)
|
||||||
// We use zero as our timeout since we know there is stuff there
|
// We use zero as our timeout since we know there is stuff there
|
||||||
msg = MessageFromPort(0);
|
msg = MessageFromPort(0);
|
||||||
// Add messages to queue
|
|
||||||
if (msg)
|
if (msg)
|
||||||
_AddMessagePriv(msg);
|
_AddMessagePriv(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop: As long as there are messages in the queue and the port is
|
// loop: As long as there are messages in the queue and the port is
|
||||||
// empty... and we are not terminating, of course.
|
// empty... and we are not terminating, of course.
|
||||||
bool dispatchNextMessage = true;
|
bool dispatchNextMessage = true;
|
||||||
while (!fTerminating && dispatchNextMessage) {
|
while (!fTerminating && dispatchNextMessage) {
|
||||||
PRINT(("LOOPER: inner loop\n"));
|
PRINT(("LOOPER: inner loop\n"));
|
||||||
// Get next message from queue (assign to fLastMessage)
|
// Get next message from queue (assign to fLastMessage)
|
||||||
fLastMessage = fQueue->NextMessage();
|
fLastMessage = fQueue->NextMessage();
|
||||||
|
|
||||||
// Lock the looper
|
|
||||||
Lock();
|
Lock();
|
||||||
|
|
||||||
if (!fLastMessage) {
|
if (!fLastMessage) {
|
||||||
// No more messages: Unlock the looper and terminate the
|
// No more messages: Unlock the looper and terminate the
|
||||||
// dispatch loop.
|
// dispatch loop.
|
||||||
@@ -1255,61 +1236,34 @@ BLooper::task_looper()
|
|||||||
(char*)&fLastMessage->what));
|
(char*)&fLastMessage->what));
|
||||||
DBG(fLastMessage->PrintToStream());
|
DBG(fLastMessage->PrintToStream());
|
||||||
|
|
||||||
// Get the target handler
|
// Get the target handler
|
||||||
#ifdef USING_MESSAGE4
|
|
||||||
// Use the private BMessage accessor to determine if we are
|
|
||||||
// using the preferred handler, or if a target has been
|
|
||||||
// specified
|
|
||||||
BHandler *handler = NULL;
|
BHandler *handler = NULL;
|
||||||
BMessage::Private messagePrivate(fLastMessage);
|
BMessage::Private messagePrivate(fLastMessage);
|
||||||
bool usePreferred = messagePrivate.UsePreferredTarget();
|
bool usePreferred = messagePrivate.UsePreferredTarget();
|
||||||
#else
|
|
||||||
// Use BMessage friend functions to determine if we are using the
|
|
||||||
// preferred handler, or if a target has been specified
|
|
||||||
BHandler* handler = NULL;
|
|
||||||
bool usePreferred = _use_preferred_target_(fLastMessage);
|
|
||||||
#endif
|
|
||||||
if (usePreferred) {
|
if (usePreferred) {
|
||||||
PRINT(("LOOPER: use preferred target\n"));
|
PRINT(("LOOPER: use preferred target\n"));
|
||||||
handler = fPreferred;
|
handler = fPreferred;
|
||||||
|
if (handler == NULL)
|
||||||
|
handler = this;
|
||||||
} else {
|
} else {
|
||||||
PRINT(("LOOPER: don't use preferred target\n"));
|
|
||||||
/**
|
|
||||||
@note Here is where all the token stuff starts to
|
|
||||||
make sense. How, exactly, do we determine
|
|
||||||
what the target BHandler is? If we look at
|
|
||||||
BMessage, we see an int32 field, fTarget.
|
|
||||||
Amazingly, we happen to have a global mapping
|
|
||||||
of BHandler pointers to int32s!
|
|
||||||
*/
|
|
||||||
PRINT(("LOOPER: use: %ld\n", _get_message_target_(fLastMessage)));
|
|
||||||
#ifndef USING_MESSAGE4
|
|
||||||
gDefaultTokens.GetToken(_get_message_target_(fLastMessage),
|
|
||||||
B_HANDLER_TOKEN, (void **)&handler);
|
|
||||||
#else
|
|
||||||
gDefaultTokens.GetToken(messagePrivate.GetTarget(),
|
gDefaultTokens.GetToken(messagePrivate.GetTarget(),
|
||||||
B_HANDLER_TOKEN, (void **)&handler);
|
B_HANDLER_TOKEN, (void **)&handler);
|
||||||
#endif
|
|
||||||
PRINT(("LOOPER: handler: %p, this: %p\n", handler, this));
|
PRINT(("LOOPER: use %ld, handler: %p, this: %p\n",
|
||||||
|
messagePrivate.GetTarget(), handler, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!handler) {
|
// Is this a scripting message? (BMessage::HasSpecifiers())
|
||||||
PRINT(("LOOPER: no target handler, use this\n"));
|
if (handler != NULL && fLastMessage->HasSpecifiers()) {
|
||||||
handler = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is this a scripting message? (BMessage::HasSpecifiers())
|
|
||||||
if (fLastMessage->HasSpecifiers()) {
|
|
||||||
int32 index = 0;
|
int32 index = 0;
|
||||||
// Make sure the current specifier is kosher
|
// Make sure the current specifier is kosher
|
||||||
if (fLastMessage->GetCurrentSpecifier(&index) == B_OK)
|
if (fLastMessage->GetCurrentSpecifier(&index) == B_OK)
|
||||||
handler = resolve_specifier(handler, fLastMessage);
|
handler = resolve_specifier(handler, fLastMessage);
|
||||||
} else {
|
|
||||||
PRINT(("LOOPER: no scripting message\n"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
// Do filtering
|
// Do filtering
|
||||||
handler = _TopLevelFilter(fLastMessage, handler);
|
handler = _TopLevelFilter(fLastMessage, handler);
|
||||||
PRINT(("LOOPER: _TopLevelFilter(): %p\n", handler));
|
PRINT(("LOOPER: _TopLevelFilter(): %p\n", handler));
|
||||||
if (handler && handler->Looper() == this)
|
if (handler && handler->Looper() == this)
|
||||||
@@ -1317,18 +1271,18 @@ BLooper::task_looper()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock the looper
|
// Unlock the looper
|
||||||
Unlock();
|
Unlock();
|
||||||
|
|
||||||
// Delete the current message (fLastMessage)
|
// Delete the current message (fLastMessage)
|
||||||
if (fLastMessage) {
|
if (fLastMessage) {
|
||||||
delete fLastMessage;
|
delete fLastMessage;
|
||||||
fLastMessage = NULL;
|
fLastMessage = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are any messages on the port?
|
// Are any messages on the port?
|
||||||
if (port_count(fMsgPort) > 0) {
|
if (port_count(fMsgPort) > 0) {
|
||||||
// Do outer loop
|
// Do outer loop
|
||||||
dispatchNextMessage = false;
|
dispatchNextMessage = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2243,6 +2243,8 @@ BWindow::task_looper()
|
|||||||
|
|
||||||
if (usePreferred) {
|
if (usePreferred) {
|
||||||
handler = PreferredHandler();
|
handler = PreferredHandler();
|
||||||
|
if (handler == NULL)
|
||||||
|
handler = this;
|
||||||
} else {
|
} else {
|
||||||
gDefaultTokens.GetToken(messagePrivate.GetTarget(),
|
gDefaultTokens.GetToken(messagePrivate.GetTarget(),
|
||||||
B_HANDLER_TOKEN, (void **)&handler);
|
B_HANDLER_TOKEN, (void **)&handler);
|
||||||
|
|||||||
Reference in New Issue
Block a user