BLooper: Add DispatchExternalMessage()
* This is primarily a service method for ports of widget tool kits that require single-threaded GUI. DispatchExternalMessage() calls DispatchMessage(), but also sets fLastMessage, so that [Detach]CurrentMessage() work correctly. This allows to detach a message in DispatchMessage() when called from the window thread, add it to a global queue, and later process the queued messages in a different thread that calls DispatchExternalMessage(). * BLooper/BWindow: Make sure fLastMessage is accessed only when locked.
This commit is contained in:
parent
57973ac96b
commit
5d7f782d4e
@ -52,6 +52,8 @@ public:
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
BMessage* CurrentMessage() const;
|
||||
BMessage* DetachCurrentMessage();
|
||||
void DispatchExternalMessage(BMessage* message,
|
||||
BHandler* handler, bool& _detached);
|
||||
BMessageQueue* MessageQueue() const;
|
||||
bool IsMessageWaiting() const;
|
||||
|
||||
|
@ -300,6 +300,22 @@ BLooper::DetachCurrentMessage()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BLooper::DispatchExternalMessage(BMessage* message, BHandler* handler,
|
||||
bool& _detached)
|
||||
{
|
||||
AssertLocked();
|
||||
|
||||
BMessage* previousMessage = fLastMessage;
|
||||
fLastMessage = message;
|
||||
|
||||
DispatchMessage(message, handler);
|
||||
|
||||
_detached = fLastMessage == NULL;
|
||||
fLastMessage = previousMessage;
|
||||
}
|
||||
|
||||
|
||||
BMessageQueue*
|
||||
BLooper::MessageQueue() const
|
||||
{
|
||||
@ -1115,11 +1131,14 @@ BLooper::task_looper()
|
||||
bool dispatchNextMessage = true;
|
||||
while (!fTerminating && dispatchNextMessage) {
|
||||
PRINT(("LOOPER: inner loop\n"));
|
||||
// Get next message from queue (assign to fLastMessage)
|
||||
fLastMessage = fDirectTarget->Queue()->NextMessage();
|
||||
// Get next message from queue (assign to fLastMessage after
|
||||
// locking)
|
||||
BMessage* message = fDirectTarget->Queue()->NextMessage();
|
||||
|
||||
Lock();
|
||||
|
||||
fLastMessage = message;
|
||||
|
||||
if (!fLastMessage) {
|
||||
// No more messages: Unlock the looper and terminate the
|
||||
// dispatch loop.
|
||||
@ -1173,14 +1192,15 @@ BLooper::task_looper()
|
||||
return;
|
||||
}
|
||||
|
||||
message = fLastMessage;
|
||||
fLastMessage = NULL;
|
||||
|
||||
// Unlock the looper
|
||||
Unlock();
|
||||
|
||||
// Delete the current message (fLastMessage)
|
||||
if (fLastMessage) {
|
||||
delete fLastMessage;
|
||||
fLastMessage = NULL;
|
||||
}
|
||||
if (message != NULL)
|
||||
delete message;
|
||||
|
||||
// Are any messages on the port?
|
||||
if (port_count(fMsgPort) > 0) {
|
||||
|
@ -3037,12 +3037,17 @@ BWindow::task_looper()
|
||||
|
||||
bool dispatchNextMessage = true;
|
||||
while (!fTerminating && dispatchNextMessage) {
|
||||
// Get next message from queue (assign to fLastMessage)
|
||||
fLastMessage = fDirectTarget->Queue()->NextMessage();
|
||||
// Get next message from queue (assign to fLastMessage after
|
||||
// locking)
|
||||
BMessage* message = fDirectTarget->Queue()->NextMessage();
|
||||
|
||||
// Lock the looper
|
||||
if (!Lock())
|
||||
if (!Lock()) {
|
||||
delete message;
|
||||
break;
|
||||
}
|
||||
|
||||
fLastMessage = message;
|
||||
|
||||
if (fLastMessage == NULL) {
|
||||
// No more messages: Unlock the looper and terminate the
|
||||
|
Loading…
Reference in New Issue
Block a user