diff --git a/src/servers/app/AppServer.cpp b/src/servers/app/AppServer.cpp index fb346bc1d0..2798ea772e 100644 --- a/src/servers/app/AppServer.cpp +++ b/src/servers/app/AppServer.cpp @@ -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); } diff --git a/src/servers/app/Jamfile b/src/servers/app/Jamfile index e462470683..1551aedd22 100644 --- a/src/servers/app/Jamfile +++ b/src/servers/app/Jamfile @@ -76,6 +76,7 @@ Server app_server : PicturePlayer.cpp PNGDump.cpp RAMLinkMsgReader.cpp + MessageLooper.cpp # Manager Classes CursorManager.cpp diff --git a/src/servers/app/MessageLooper.cpp b/src/servers/app/MessageLooper.cpp new file mode 100644 index 0000000000..d563046bfd --- /dev/null +++ b/src/servers/app/MessageLooper.cpp @@ -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 + + +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; +} + diff --git a/src/servers/app/MessageLooper.h b/src/servers/app/MessageLooper.h new file mode 100644 index 0000000000..db6141f671 --- /dev/null +++ b/src/servers/app/MessageLooper.h @@ -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 +#include +#include + + +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 */ diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index 1703eeb576..8b01d6c6a5 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -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(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; -} - diff --git a/src/servers/app/ServerApp.h b/src/servers/app/ServerApp.h index bd7b257a1b..81de13ea0b 100644 --- a/src/servers/app/ServerApp.h +++ b/src/servers/app/ServerApp.h @@ -13,13 +13,13 @@ #define _SERVERAPP_H_ -#include -#include -#include - +#include "MessageLooper.h" #include "SubWindowList.h" #include "BGet++.h" +#include + + 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_ diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 5128cc6eeb..d76a53cfae 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -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 diff --git a/src/servers/app/ServerWindow.h b/src/servers/app/ServerWindow.h index 9ccb1b1a2d..7f748a6632 100644 --- a/src/servers/app/ServerWindow.h +++ b/src/servers/app/ServerWindow.h @@ -22,6 +22,7 @@ #include #include +#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;