The Desktop class now gets its own message processing loop: moved application

creation/deletion (and management) over to that class.
ServerApp now gets a desktop pointer, and no longer uses gDesktop.
Converted private MessageLooper::_MessagePort() to a public method MessagePort()
so that the looper can be addressed from elsewhere without using PostMessage().
Added a real basic message loop to MessageLooper::_MessageLoop().
BApplication now only asks the app_server to get its desktop object which should
now be used for everything that's not in the realm of the application.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13824 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2005-07-25 21:08:34 +00:00
parent 5845b8c325
commit 770c05d6cc
11 changed files with 320 additions and 260 deletions
+19 -181
View File
@@ -59,9 +59,6 @@
#endif
static const uint32 kMsgShutdownServer = 'shuT';
// Globals
Desktop *gDesktop;
@@ -83,10 +80,8 @@ AppServer::AppServer() : BApplication (SERVER_SIGNATURE),
#else
AppServer::AppServer() :
#endif
fAppListLock("application list"),
fCursorSem(-1),
fCursorArea(-1),
fShutdownSemaphore(-1)
fCursorArea(-1)
{
fMessagePort = create_port(200, SERVER_PORT_NAME);
if (fMessagePort == B_NO_MORE_PORTS)
@@ -164,6 +159,7 @@ AppServer::AppServer() :
gGUIColorSet.SetToDefaults();
gScreenManager = new ScreenManager();
gScreenManager->Run();
// the system palette needs to be initialized before the desktop,
// since it is used there already
@@ -254,11 +250,6 @@ AppServer::PicassoThread(void *data)
snooze(1000000);
}
// app_server is about to quit
// wait some more, and then make sure it'll shutdown everything
snooze(2000000);
sAppServer->PostMessage(kMsgShutdownServer);
return 0;
}
@@ -419,94 +410,19 @@ void
AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
{
switch (code) {
case AS_CREATE_APP:
case AS_GET_DESKTOP:
{
// Create the ServerApp to node monitor a new BApplication
// Attached data:
// 1) port_id - receiver port of a regular app
// 2) port_id - client looper port - for sending messages to the client
// 2) team_id - app's team ID
// 3) int32 - handler token of the regular app
// 4) char * - signature of the regular app
// Find the necessary data
team_id clientTeamID = -1;
port_id clientLooperPort = -1;
port_id clientReplyPort = -1;
int32 htoken = B_NULL_TOKEN;
char *appSignature = NULL;
msg.Read<port_id>(&clientReplyPort);
msg.Read<port_id>(&clientLooperPort);
msg.Read<team_id>(&clientTeamID);
msg.Read<int32>(&htoken);
if (msg.ReadString(&appSignature) != B_OK)
port_id replyPort;
if (msg.Read<port_id>(&replyPort) < B_OK)
break;
ServerApp *app = new ServerApp(clientReplyPort, clientLooperPort,
clientTeamID, htoken, appSignature);
if (app->InitCheck() == B_OK
&& app->Run()) {
// add the new ServerApp to the known list of ServerApps
fAppListLock.Lock();
fAppList.AddItem(app);
fAppListLock.Unlock();
} else {
delete app;
int32 userID;
msg.Read<int32>(&userID);
// if everything went well, ServerApp::Run() will notify
// the client - but since it didn't, we do it here
BPrivate::LinkSender reply(clientReplyPort);
reply.StartMessage(SERVER_FALSE);
reply.Flush();
}
// This is necessary because BPortLink::ReadString allocates memory
free(appSignature);
break;
}
case AS_DELETE_APP:
{
// Delete a ServerApp. Received only from the respective ServerApp when a
// BApplication asks it to quit.
// Attached Data:
// 1) thread_id - thread ID of the ServerApp to be deleted
thread_id thread = -1;
if (msg.Read<thread_id>(&thread) < B_OK)
break;
fAppListLock.Lock();
// Run through the list of apps and nuke the proper one
int32 count = fAppList.CountItems();
ServerApp *removeApp = NULL;
for (int32 i = 0; i < count; i++) {
ServerApp *app = (ServerApp *)fAppList.ItemAt(i);
if (app != NULL && app->Thread() == thread) {
fAppList.RemoveItem(i);
removeApp = app;
break;
}
}
fAppListLock.Unlock();
if (removeApp != NULL)
removeApp->Quit(fShutdownSemaphore);
if (fQuitting && count <= 1) {
// wait for the last app to die
acquire_sem_etc(fShutdownSemaphore, fShutdownCount, B_RELATIVE_TIMEOUT, 500000);
PostMessage(kMsgShutdownServer);
}
BPrivate::LinkSender reply(replyPort);
reply.StartMessage(B_OK);
reply.Attach<port_id>(gDesktop->MessagePort());
reply.Flush();
break;
}
@@ -543,54 +459,25 @@ AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
#if TEST_MODE
case B_QUIT_REQUESTED:
{
// We've been asked to quit, so (for now) broadcast to all
// test apps to quit. This situation will occur only when the server
// is compiled as a regular Be application.
fAppListLock.Lock();
fShutdownSemaphore = create_sem(0, "app_server shutdown");
fShutdownCount = fAppList.CountItems();
fAppListLock.Unlock();
gDesktop->PostMessage(B_QUIT_REQUESTED);
fQuitting = true;
BroadcastToAllApps(AS_QUIT_APP);
// We now need to process the remaining AS_DELETE_APP messages and
// wait for the kMsgShutdownServer message.
// If an application does not quit as asked, the picasso thread
// will send us this message in 2-3 seconds.
// if there are no apps to quit, shutdown directly
if (fShutdownCount == 0)
PostMessage(kMsgShutdownServer);
break;
case kMsgShutdownServer:
{
// let's kill all remaining applications
fAppListLock.Lock();
int32 count = fAppList.CountItems();
for (int32 i = 0; i < count; i++) {
ServerApp *app = (ServerApp*)fAppList.ItemAt(i);
team_id clientTeam = app->ClientTeam();
app->Quit();
kill_team(clientTeam);
}
// wait for the last app to die
if (count > 0)
acquire_sem_etc(fShutdownSemaphore, fShutdownCount, B_RELATIVE_TIMEOUT, 250000);
// we just wait for the desktop to kill itself
status_t status;
wait_for_thread(gDesktop->Thread(), &status);
kill_thread(fPicassoThreadID);
fAppListLock.Unlock();
delete gDesktop;
delete gBitmapManager;
delete gFontServer;
// TODO: deleting the font server results in an endless loop somewhere
// down in FreeType code - smells like memory corruption
//delete gFontServer;
// we are now clear to exit
exit(0);
@@ -635,7 +522,6 @@ AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
BPrivate::PortLink replyLink(replyPort);
replyLink.StartMessage(error);
replyLink.Flush();
break;
}
@@ -646,58 +532,10 @@ AppServer::DispatchMessage(int32 code, BPrivate::PortLink &msg)
}
}
/*!
\brief Finds the application with the given signature
\param sig MIME signature of the application to find
\return the corresponding ServerApp or NULL if not found
This call should be made only when necessary because it locks the app list
while it does its searching.
*/
ServerApp *
AppServer::FindApp(const char *signature)
{
if (!signature)
return NULL;
BAutolock locker(fAppListLock);
for (int32 i = 0; i < fAppList.CountItems(); i++) {
ServerApp *app = (ServerApp*)fAppList.ItemAt(i);
if (app && !strcasecmp(app->Signature(), signature))
return app;
}
return NULL;
}
// #pragma mark -
/*!
\brief Send a quick (no attachments) message to all applications
Quite useful for notification for things like server shutdown, system
color changes, etc.
*/
void
BroadcastToAllApps(const int32 &code)
{
BAutolock locker(sAppServer->fAppListLock);
for (int32 i = 0; i < sAppServer->fAppList.CountItems(); i++) {
ServerApp *app = (ServerApp *)sAppServer->fAppList.ItemAt(i);
if (!app) {
printf("PANIC in Broadcast()\n");
continue;
}
app->PostMessage(code);
}
}
/*!
\brief Entry function to run the entire server
\param argc Number of command-line arguments present