2005-07-23 22:30:48 +04:00
|
|
|
/*
|
2007-03-25 16:43:13 +04:00
|
|
|
* Copyright 2005-2007, Haiku.
|
2005-07-23 22:30:48 +04:00
|
|
|
* Distributed under the terms of the MIT License.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Axel Dörfler, axeld@pinc-software.de
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "MessageLooper.h"
|
|
|
|
|
|
|
|
#include <Autolock.h>
|
2005-07-26 01:08:34 +04:00
|
|
|
#include <stdio.h>
|
2005-11-13 02:27:14 +03:00
|
|
|
#include <string.h>
|
2005-07-23 22:30:48 +04:00
|
|
|
|
|
|
|
|
|
|
|
MessageLooper::MessageLooper(const char* name)
|
|
|
|
: BLocker(name),
|
2007-03-25 16:43:13 +04:00
|
|
|
fThread(-1),
|
|
|
|
fQuitting(false),
|
|
|
|
fDeathSemaphore(-1)
|
2005-07-23 22:30:48 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MessageLooper::~MessageLooper()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
MessageLooper::Run()
|
|
|
|
{
|
|
|
|
BAutolock locker(this);
|
|
|
|
|
|
|
|
fQuitting = false;
|
|
|
|
|
|
|
|
char name[B_OS_NAME_LENGTH];
|
|
|
|
_GetLooperName(name, sizeof(name));
|
|
|
|
|
|
|
|
// Spawn our message-monitoring thread
|
2006-11-30 16:15:15 +03:00
|
|
|
fThread = spawn_thread(_message_thread, name, B_DISPLAY_PRIORITY, this);
|
2005-07-23 22:30:48 +04:00
|
|
|
if (fThread < B_OK) {
|
|
|
|
fQuitting = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resume_thread(fThread) != B_OK) {
|
|
|
|
fQuitting = true;
|
|
|
|
kill_thread(fThread);
|
|
|
|
fThread = -1;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
MessageLooper::Quit()
|
|
|
|
{
|
2005-07-24 21:13:02 +04:00
|
|
|
fQuitting = true;
|
|
|
|
_PrepareQuit();
|
|
|
|
|
|
|
|
if (fThread < B_OK) {
|
|
|
|
// thread has not been started yet
|
|
|
|
delete this;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fThread == find_thread(NULL)) {
|
|
|
|
// called from our message looper
|
|
|
|
delete this;
|
|
|
|
exit_thread(0);
|
|
|
|
} else {
|
|
|
|
// called from a different thread
|
|
|
|
PostMessage(kMsgQuitLooper);
|
|
|
|
}
|
2005-07-23 22:30:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Send a message to the looper without any attachments
|
|
|
|
\param code ID code of the message to post
|
|
|
|
*/
|
2005-11-25 16:49:29 +03:00
|
|
|
status_t
|
2005-12-12 16:12:51 +03:00
|
|
|
MessageLooper::PostMessage(int32 code, bigtime_t timeout)
|
2005-07-23 22:30:48 +04:00
|
|
|
{
|
2005-07-26 01:08:34 +04:00
|
|
|
BPrivate::LinkSender link(MessagePort());
|
2005-07-23 22:30:48 +04:00
|
|
|
link.StartMessage(code);
|
2005-12-12 16:12:51 +03:00
|
|
|
return link.Flush(timeout);
|
2005-11-25 16:49:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*static*/
|
|
|
|
status_t
|
|
|
|
MessageLooper::WaitForQuit(sem_id semaphore, bigtime_t timeout)
|
|
|
|
{
|
|
|
|
status_t status;
|
|
|
|
do {
|
|
|
|
status = acquire_sem_etc(semaphore, 1, B_RELATIVE_TIMEOUT, timeout);
|
|
|
|
} while (status == B_INTERRUPTED);
|
|
|
|
|
|
|
|
if (status == B_TIMED_OUT)
|
|
|
|
return status;
|
|
|
|
|
|
|
|
return B_OK;
|
2005-07-23 22:30:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-24 21:13:02 +04:00
|
|
|
void
|
|
|
|
MessageLooper::_PrepareQuit()
|
|
|
|
{
|
|
|
|
// to be implemented by subclasses
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-23 22:30:48 +04:00
|
|
|
void
|
|
|
|
MessageLooper::_GetLooperName(char* name, size_t length)
|
|
|
|
{
|
2007-08-30 04:09:43 +04:00
|
|
|
sem_id semaphore = Sem();
|
|
|
|
sem_info info;
|
|
|
|
if (get_sem_info(semaphore, &info) == B_OK)
|
|
|
|
strlcpy(name, info.name, length);
|
|
|
|
else
|
|
|
|
strlcpy(name, "unnamed looper", length);
|
2005-07-23 22:30:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
MessageLooper::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
MessageLooper::_MessageLooper()
|
|
|
|
{
|
2005-07-26 01:08:34 +04:00
|
|
|
BPrivate::LinkReceiver& receiver = fLink.Receiver();
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
int32 code;
|
|
|
|
status_t status = receiver.GetNextMessage(code);
|
|
|
|
if (status < B_OK) {
|
|
|
|
// that shouldn't happen, it's our port
|
2007-08-30 04:09:43 +04:00
|
|
|
char name[256];
|
|
|
|
_GetLooperName(name, 256);
|
|
|
|
printf("MessageLooper \"%s\": Someone deleted our message port %ld, %s!\n",
|
|
|
|
name, receiver.Port(), strerror(status));
|
2005-07-26 01:08:34 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Lock();
|
|
|
|
|
|
|
|
if (code == kMsgQuitLooper) {
|
|
|
|
Quit();
|
|
|
|
} else
|
|
|
|
_DispatchMessage(code, receiver);
|
|
|
|
|
|
|
|
Unlock();
|
|
|
|
}
|
2005-07-23 22:30:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Message-dispatching loop starter
|
|
|
|
*/
|
|
|
|
/*static*/
|
|
|
|
int32
|
|
|
|
MessageLooper::_message_thread(void* _looper)
|
|
|
|
{
|
|
|
|
MessageLooper* looper = (MessageLooper*)_looper;
|
|
|
|
|
|
|
|
looper->_MessageLooper();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|