Factored a MessageLooper class out of ServerWindow and ServerApp. Could still

be improved a bit (Quit() and _MessageLooper() are empty right now).
Removed ServerApp::PingTarget().
Hopefully cleared some confusion about ServerApp::fClientLooperPort and fClientToken
(previously fHandlerToken), even if it's currently unused.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13807 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2005-07-23 18:30:48 +00:00
parent f95c74702f
commit 89ab121e66
8 changed files with 231 additions and 198 deletions

View File

@ -236,6 +236,9 @@ int32
AppServer::PicassoThread(void *data)
{
while (!sAppServer->fQuitting) {
// TODO: we don't need to do this anymore - dead apps are
// detected automatically
#if 0
sAppServer->fAppListLock.Lock();
for (int32 i = 0;;) {
@ -247,6 +250,7 @@ AppServer::PicassoThread(void *data)
}
sAppServer->fAppListLock.Unlock();
#endif
// we do this every second so as not to suck *too* many CPU cycles
snooze(1000000);
}

View File

@ -76,6 +76,7 @@ Server app_server :
PicturePlayer.cpp
PNGDump.cpp
RAMLinkMsgReader.cpp
MessageLooper.cpp
# Manager Classes
CursorManager.cpp

View File

@ -0,0 +1,105 @@
/*
* Copyright 2005, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
*/
#include "MessageLooper.h"
#include <Autolock.h>
MessageLooper::MessageLooper(const char* name)
: BLocker(name),
fQuitting(false)
{
}
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
fThread = spawn_thread(_message_thread, name, B_NORMAL_PRIORITY, this);
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()
{
}
/*!
\brief Send a message to the looper without any attachments
\param code ID code of the message to post
*/
void
MessageLooper::PostMessage(int32 code)
{
BPrivate::LinkSender link(_MessagePort());
link.StartMessage(code);
link.Flush();
}
void
MessageLooper::_GetLooperName(char* name, size_t length)
{
strcpy(name, "unnamed looper");
}
void
MessageLooper::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
{
}
void
MessageLooper::_MessageLooper()
{
}
/*!
\brief Message-dispatching loop starter
*/
/*static*/
int32
MessageLooper::_message_thread(void* _looper)
{
MessageLooper* looper = (MessageLooper*)_looper;
looper->_MessageLooper();
return 0;
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 2005, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
*/
#ifndef MESSAGE_LOOPER_H
#define MESSAGE_LOOPER_H
#include <PortLink.h>
#include <Locker.h>
#include <OS.h>
class MessageLooper : public BLocker {
public:
MessageLooper(const char* name);
virtual ~MessageLooper();
virtual bool Run();
virtual void Quit();
void PostMessage(int32 code);
thread_id Thread() const { return fThread; }
private:
virtual void _GetLooperName(char* name, size_t length);
virtual void _DispatchMessage(int32 code, BPrivate::LinkReceiver &link);
virtual void _MessageLooper();
virtual port_id _MessagePort() const = 0;
static int32 _message_thread(void *_looper);
protected:
thread_id fThread;
BPrivate::PortLink fLink;
bool fQuitting;
};
#endif /* MESSAGE_LOOPER_H */

View File

@ -79,20 +79,18 @@ static const uint32 kMsgAppQuit = 'appQ';
*/
ServerApp::ServerApp(port_id clientReplyPort, port_id clientLooperPort,
team_id clientTeam, int32 handlerID, const char* signature)
:
fClientReplyPort(clientReplyPort),
: MessageLooper("application"),
fMessagePort(-1),
fClientReplyPort(clientReplyPort),
fClientLooperPort(clientLooperPort),
fClientToken(handlerID),
fSignature(signature),
fThread(-1),
fClientTeam(clientTeam),
fWindowListLock("window list"),
fAppCursor(NULL),
fCursorHidden(false),
fIsActive(false),
//fHandlerToken(handlerID),
fSharedMem("shared memory"),
fQuitting(false)
fSharedMem("shared memory")
{
if (fSignature == "")
fSignature = "application/no-signature";
@ -230,21 +228,9 @@ ServerApp::InitCheck()
bool
ServerApp::Run()
{
fQuitting = false;
// Unlike a BApplication, a ServerApp is *supposed* to return immediately
// when its Run() function is called.
fThread = spawn_thread(_message_thread, Signature(), B_NORMAL_PRIORITY, this);
if (fThread < B_OK)
if (!MessageLooper::Run())
return false;
if (resume_thread(fThread) != B_OK) {
fQuitting = true;
kill_thread(fThread);
fThread = -1;
return false;
}
// Let's tell the client how to talk with us
fLink.StartMessage(SERVER_TRUE);
fLink.Attach<int32>(fMessagePort);
@ -278,48 +264,6 @@ ServerApp::Quit(sem_id shutdownSemaphore)
}
/*!
\brief Pings the target app to make sure it's still working
\return true if target is still "alive" and false if "He's dead, Jim."
"But that's impossible..."
This function is called by the app_server thread to ensure that
the target app still exists. We do this not by sending a message
but by calling get_port_info. We don't want to send ping messages
just because the app might simply be hung. If this is the case, it
should be up to the user to kill it. If the app has been killed, its
ports will be invalid. Thus, if get_port_info returns an error, we
tell the app_server to delete the respective ServerApp.
*/
bool
ServerApp::PingTarget()
{
// ToDo: this function doesn't make any sense; if the client dies we are
// aware of it anyway at this point. This would only make sense if we
// actually send the team a message to see if it's still responsive.
team_info info;
if (get_team_info(fClientTeam, &info) != B_OK) {
BPrivate::LinkSender link(gAppServerPort);
link.StartMessage(AS_DELETE_APP);
link.Attach(&fThread, sizeof(thread_id));
link.Flush();
return false;
}
return true;
}
/*!
\brief Send a message to the ServerApp with no attachments
\param code ID code of the message to post
*/
void
ServerApp::PostMessage(int32 code)
{
BPrivate::LinkSender link(fMessagePort);
link.StartMessage(code);
link.Flush();
}
/*!
\brief Send a message to the ServerApp's BApplication
\param msg The message to send
@ -338,6 +282,7 @@ ServerApp::SendMessageToClient(const BMessage *msg) const
delete [] buffer;
}
/*!
\brief Sets the ServerApp's active status
\param value The new status of the ServerApp.
@ -365,17 +310,15 @@ ServerApp::SetAppCursor(void)
}
/*!
\brief The thread function ServerApps use to monitor messages
\param data Pointer to the thread's ServerApp object
*/
int32
ServerApp::_message_thread(void *_app)
void
ServerApp::_GetLooperName(char* name, size_t length)
{
ServerApp *app = (ServerApp *)_app;
app->_MessageLooper();
return 0;
#ifdef __HAIKU__
strlcpy(name, Signature(), length);
#else
strncpy(name, Signature(), length);
name[length - 1] = '\0';
#endif
}
@ -2307,10 +2250,3 @@ ServerApp::ClientTeam() const
return fClientTeam;
}
thread_id
ServerApp::Thread() const
{
return fThread;
}

View File

@ -13,13 +13,13 @@
#define _SERVERAPP_H_
#include <OS.h>
#include <String.h>
#include <PortLink.h>
#include "MessageLooper.h"
#include "SubWindowList.h"
#include "BGet++.h"
#include <String.h>
class AreaPool;
class BMessage;
class BList;
@ -36,92 +36,76 @@ namespace BPrivate {
\class ServerApp ServerApp.h
\brief Counterpart to BApplication within the app_server
*/
class ServerApp {
public:
ServerApp(port_id clientAppPort, port_id clientLooperPort,
team_id clientTeamID, int32 handlerID, const char* signature);
~ServerApp();
class ServerApp : public MessageLooper {
public:
ServerApp(port_id clientAppPort, port_id clientLooperPort,
team_id clientTeamID, int32 handlerID,
const char* signature);
virtual ~ServerApp();
status_t InitCheck();
bool Run();
void Quit(sem_id shutdownSemaphore = -1);
status_t InitCheck();
virtual bool Run();
void Quit(sem_id shutdownSemaphore = -1);
/*!
\brief Determines whether the application is the active one
\return true if active, false if not.
*/
bool IsActive(void) const { return fIsActive; }
void Activate(bool value);
/*!
\brief Determines whether the application is the active one
\return true if active, false if not.
*/
bool IsActive(void) const { return fIsActive; }
void Activate(bool value);
bool PingTarget(void);
void SendMessageToClient(const BMessage* msg) const;
void PostMessage(int32 code);
void SendMessageToClient(const BMessage* msg) const;
void SetAppCursor(void);
void SetAppCursor(void);
team_id ClientTeam() const;
const char *Signature() const { return fSignature.String(); }
team_id ClientTeam() const;
thread_id Thread() const;
void RemoveWindow(ServerWindow* window);
const char *Signature() const { return fSignature.String(); }
int32 CountBitmaps() const;
ServerBitmap *FindBitmap(int32 token) const;
void RemoveWindow(ServerWindow* window);
int32 CountPictures() const;
ServerPicture *FindPicture(int32 token) const;
int32 CountBitmaps() const;
ServerBitmap *FindBitmap(int32 token) const;
AreaPool *AppAreaPool() { return &fSharedMem; }
int32 CountPictures() const;
ServerPicture *FindPicture(int32 token) const;
// ToDo: public?
SubWindowList fAppSubWindowList;
AreaPool *AppAreaPool() { return &fSharedMem; }
private:
virtual void _DispatchMessage(int32 code, BPrivate::LinkReceiver &link);
virtual void _MessageLooper();
virtual void _GetLooperName(char* name, size_t size);
virtual port_id _MessagePort() const { return fMessagePort; }
SubWindowList fAppSubWindowList;
port_id fMessagePort;
port_id fClientReplyPort;
// our BApplication's event port
private:
void _DispatchMessage(int32 code, BPrivate::LinkReceiver &link);
void _MessageLooper();
port_id fClientLooperPort;
int32 fClientToken;
// To send a BMessage to the client (port + token)
static int32 _message_thread(void *data);
BString fSignature;
team_id fClientTeam;
// our BApplication's event port
port_id fClientReplyPort;
// port we receive messages from our BApplication
port_id fMessagePort;
// TODO: find out why there is both the app port and the looper port. Do
// we really need both? Actually, we aren't using any of these ports,
// as BAppServerLink/BPortlink's messages always contain the reply port
// To send a message to the client, write a BMessage to this port
port_id fClientLooperPort;
BLocker fWindowListLock;
BList fWindowList;
BString fSignature;
// TODO:
// - Are really Bitmaps and Pictures stored per application and not globally ?
// - As we reference these stuff by token, what about putting them in hash tables ?
BList fBitmapList;
BList fPictureList;
thread_id fThread;
team_id fClientTeam;
ServerCursor *fAppCursor;
bool fCursorHidden;
BPrivate::PortLink fLink;
bool fIsActive;
BLocker fWindowListLock;
BList fWindowList;
// TODO:
// - Are really Bitmaps and Pictures stored per application and not globally ?
// - As we reference these stuff by token, what about putting them in hash tables ?
BList fBitmapList;
BList fPictureList;
ServerCursor *fAppCursor;
bool fCursorHidden;
bool fIsActive;
// token ID of the BApplication's BHandler object.
// Used for BMessage target specification
// TODO: Is it still needed ? We aren't using it.
//int32 fHandlerToken;
AreaPool fSharedMem;
bool fQuitting;
AreaPool fSharedMem;
};
#endif // _SERVERAPP_H_

View File

@ -76,7 +76,7 @@ static const uint32 kMsgWindowQuit = 'winQ';
*/
ServerWindow::ServerWindow(const char *title, ServerApp *app,
port_id clientPort, port_id looperPort, int32 handlerID)
: BLocker(title && *title ? title : "Unnamed Window"),
: MessageLooper(title && *title ? title : "Unnamed Window"),
fTitle(title),
fServerApp(app),
fWinBorder(NULL),
@ -84,7 +84,6 @@ ServerWindow::ServerWindow(const char *title, ServerApp *app,
fMessagePort(-1),
fClientReplyPort(clientPort),
fClientLooperPort(looperPort),
fQuitting(false),
fClientViewsWithInvalidCoords(B_VIEW_RESIZED),
fHandlerToken(handlerID),
fCurrentLayer(NULL)
@ -145,22 +144,9 @@ ServerWindow::Init(BRect frame, uint32 look, uint32 feel, uint32 flags, uint32 w
bool
ServerWindow::Run()
{
BAutolock locker(this);
char name[B_OS_NAME_LENGTH];
snprintf(name, sizeof(name), "w:%ld:%s", ClientTeam(), Title());
// Spawn our message-monitoring thread
fThread = spawn_thread(_message_thread, name, B_NORMAL_PRIORITY, this);
if (fThread < B_OK)
if (!MessageLooper::Run())
return false;
if (resume_thread(fThread) != B_OK) {
kill_thread(fThread);
fThread = -1;
return false;
}
// Send a reply to our window - it is expecting fMessagePort
// port and some other info
@ -206,16 +192,10 @@ ServerWindow::Quit()
}
/*!
\brief Send a message to the ServerWindow with no attachments
\param code ID code of the message to post
*/
void
ServerWindow::PostMessage(int32 code)
ServerWindow::_GetLooperName(char* name, size_t length)
{
BPrivate::LinkSender link(fMessagePort);
link.StartMessage(code);
link.Flush();
snprintf(name, length, "w:%ld:%s", ClientTeam(), Title());
}
@ -2130,19 +2110,6 @@ ServerWindow::_DispatchGraphicsMessage(int32 code, BPrivate::LinkReceiver &link)
driver->ConstrainClippingRegion(NULL);
}
/*!
\brief Message-dispatching loop starter
\param data The thread's ServerWindow
*/
int32
ServerWindow::_message_thread(void *_window)
{
ServerWindow *window = (ServerWindow *)_window;
window->_MessageLooper();
return 0;
}
/*!
\brief Message-dispatching loop for the ServerWindow

View File

@ -22,6 +22,7 @@
#include <String.h>
#include <Window.h>
#include "MessageLooper.h"
#include "SubWindowList.h"
#include "TokenSpace.h"
@ -52,7 +53,7 @@ struct window_info;
coordinating and linking a window's WinBorder half with its messaging half, dispatching
mouse and key events from the server to its window, and other such things.
*/
class ServerWindow : public BLocker {
class ServerWindow : public MessageLooper {
public:
ServerWindow(const char *title, ServerApp *app,
port_id clientPort, port_id looperPort,
@ -62,15 +63,13 @@ public:
status_t Init(BRect frame, uint32 look,
uint32 feel, uint32 flags,
uint32 workspace);
bool Run();
void Quit();
virtual bool Run();
virtual void Quit();
void ReplaceDecorator();
void Show();
void Hide();
void PostMessage(int32 code);
// methods for sending various messages to client.
void NotifyQuitRequested();
void NotifyMinimize(bool minimize);
@ -102,7 +101,6 @@ public:
// related thread/team_id(s).
inline team_id ClientTeam() const { return fClientTeam; }
inline thread_id Thread() const { return fThread; }
// server "private" - try not to use.
inline int32 ClientToken() const { return fHandlerToken; }
@ -123,8 +121,8 @@ private:
void _DispatchMessage(int32 code, BPrivate::LinkReceiver &link);
void _DispatchGraphicsMessage(int32 code, BPrivate::LinkReceiver &link);
void _MessageLooper();
static int32 _message_thread(void *_window);
virtual void _GetLooperName(char* name, size_t size);
virtual port_id _MessagePort() const { return fMessagePort; }
// TODO: Move me elsewhere
status_t PictureToRegion(ServerPicture *picture,
@ -139,15 +137,11 @@ private:
WinBorder* fWinBorder;
team_id fClientTeam;
thread_id fThread;
port_id fMessagePort;
port_id fClientReplyPort;
port_id fClientLooperPort;
BPrivate::PortLink fLink;
bool fQuitting;
BMessage fClientViewsWithInvalidCoords;
int32 fServerToken;