Files
haiku-beta6/src/tests/apps/fake_app_server/AppServer.cpp
T

332 lines
7.8 KiB
C++
Raw Normal View History

//------------------------------------------------------------------------------
// Copyright (c) 2001-2005, Haiku, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: AppServer.cpp
// Author: DarkWyrm <[email protected]>
// Description: main manager object for the app_server
//
//------------------------------------------------------------------------------
#include <AppDefs.h>
#include <Accelerant.h>
#include <Entry.h>
#include <Path.h>
#include <Directory.h>
#include <PortLink.h>
#include <File.h>
#include <Message.h>
#include "AppServer.h"
#include "ServerProtocol.h"
#include "ServerApp.h"
#include <TokenSpace.h>
#if 0
#include "ColorSet.h"
#include "DisplayDriver.h"
#include "ServerCursor.h"
#include "ServerWindow.h"
#include "DefaultDecorator.h"
#include "RGBColor.h"
#include "BitmapManager.h"
#include "CursorManager.h"
#include "Utils.h"
#include "FontServer.h"
#include "Desktop.h"
#include "RootLayer.h"
#endif
#include <StopWatch.h>
#ifdef DEBUG_KEYHANDLING
# include <stdio.h>
# define KBTRACE(x) printf x
#else
# define KBTRACE(x) ;
#endif
//#define DEBUG_SERVER
#ifdef DEBUG_SERVER
# define DEBUG 1
# include <Debug.h>
# define STRACE(x) _sPrintf x
#else
# define STRACE(x) ;
#endif
// Globals
AppServer::AppServer(void)
{
fMessagePort = create_port(200, SERVER_PORT_NAME);
fAppList = new BList(0);
fQuittingServer= false;
// This is necessary to mediate access between the Poller and app_server threads
fActiveAppLock= create_sem(1,"app_server_active_sem");
// This locker is for app_server and Picasso to vy for control of the ServerApp list
fAppListLock= create_sem(1,"app_server_applist_sem");
// Spawn our thread-monitoring thread
fPicassoThreadID= spawn_thread(PicassoThread,"picasso", B_NORMAL_PRIORITY, this);
if (fPicassoThreadID >= 0)
resume_thread(fPicassoThreadID);
}
AppServer::~AppServer(void)
{
}
int32
AppServer::PicassoThread(void *data)
{
int32 i;
AppServer *appserver=(AppServer*)data;
ServerApp *app;
for(;;)
{
i = 0;
#if 1
acquire_sem(appserver->fAppListLock);
for(;;)
{
app=(ServerApp*)appserver->fAppList->ItemAt(i++);
if(!app)
break;
app->PingTarget();
}
release_sem(appserver->fAppListLock);
#endif
// we do this every other second so as not to suck *too* many CPU cycles
snooze(1000000);
}
return 0;
}
thread_id
AppServer::Run(void)
{
MainLoop();
kill_thread(fPicassoThreadID);
return 0;
}
//! Main message-monitoring loop for the regular message port - no input messages!
void
AppServer::MainLoop(void)
{
BPortLink pmsg(-1,fMessagePort);
int32 code=0;
status_t err=B_OK;
while(1)
{
STRACE(("info: AppServer::MainLoop listening on port %ld.\n", fMessagePort));
2005-06-08 10:32:24 +00:00
err=pmsg.GetNextMessage(code);
if(err<B_OK)
{
2005-06-08 10:32:24 +00:00
STRACE(("MainLoop:pmsg.GetNextMessage failed\n"));
continue;
}
switch(code)
{
case B_QUIT_REQUESTED:
case AS_CREATE_APP:
case AS_DELETE_APP:
case AS_UPDATED_CLIENT_FONTLIST:
case AS_QUERY_FONTS_CHANGED:
case AS_SET_UI_COLORS:
case AS_GET_UI_COLOR:
case AS_SET_DECORATOR:
case AS_GET_DECORATOR:
case AS_R5_SET_DECORATOR:
DispatchMessage(code,pmsg);
break;
default:
{
STRACE(("Server::MainLoop received unexpected code %ld(offset %ld)\n",
code,code-SERVER_TRUE));
break;
}
}
}
}
void
AppServer::DispatchMessage(int32 code, BPortLink &msg)
{
switch(code)
{
#if 1
case AS_CREATE_APP:
{
// 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 send 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 app_port=-1;
int32 htoken=B_NULL_TOKEN;
char *app_signature=NULL;
msg.Read<port_id>(&app_port);
msg.Read<port_id>(&clientLooperPort);
msg.Read<team_id>(&clientTeamID);
msg.Read<int32>(&htoken);
msg.ReadString(&app_signature);
// Create the ServerApp subthread for this app
acquire_sem(fAppListLock);
port_id server_listen=create_port(DEFAULT_MONITOR_PORT_SIZE, app_signature);
if(server_listen<B_OK)
{
release_sem(fAppListLock);
printf("No more ports left. Time to crash. Have a nice day! :)\n");
break;
}
ServerApp *newapp=NULL;
newapp= new ServerApp(app_port,server_listen, clientLooperPort, clientTeamID,
htoken, app_signature);
// add the new ServerApp to the known list of ServerApps
fAppList->AddItem(newapp);
release_sem(fAppListLock);
BPortLink replylink(app_port);
replylink.StartMessage(SERVER_TRUE);
replylink.Attach<int32>(newapp->fMessagePort);
replylink.Flush();
// This is necessary because BPortLink::ReadString allocates memory
if(app_signature)
free(app_signature);
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
int32 i=0,
appnum=fAppList->CountItems();
ServerApp *srvapp=NULL;
thread_id srvapp_id=-1;
if(msg.Read<thread_id>(&srvapp_id)<B_OK)
break;
acquire_sem(fAppListLock);
// Run through the list of apps and nuke the proper one
for(i= 0; i < appnum; i++)
{
srvapp=(ServerApp *)fAppList->ItemAt(i);
if(srvapp != NULL && srvapp->fMonitorThreadID== srvapp_id)
{
srvapp=(ServerApp *)fAppList->RemoveItem(i);
if(srvapp)
{
status_t temp;
wait_for_thread(srvapp_id, &temp);
delete srvapp;
srvapp= NULL;
}
break; // jump out of our for() loop
}
}
release_sem(fAppListLock);
break;
}
#endif
case AS_QUERY_FONTS_CHANGED:
{
// Seeing how the client merely wants an answer, we'll skip the BPortLink
// and all its overhead and just write the code to port.
port_id replyport;
if (msg.Read<port_id>(&replyport) < B_OK)
break;
BPortLink replylink(replyport);
replylink.StartMessage(SERVER_FALSE);
replylink.Flush();
break;
}
case AS_GET_DECORATOR:
{
// Attached Data:
// 1) port_id reply port
port_id replyport=-1;
if(msg.Read<port_id>(&replyport)<B_OK)
return;
BPortLink replylink(replyport);
replylink.StartMessage(AS_GET_DECORATOR);
replylink.AttachString("none");
replylink.Flush();
break;
}
2005-04-29 20:30:41 +00:00
case AS_UPDATED_CLIENT_FONTLIST:
case AS_SET_UI_COLORS:
case AS_SET_DECORATOR:
case AS_R5_SET_DECORATOR:
case AS_SET_SYSCURSOR_DEFAULTS:
default:
break;
}
}
int
main(int argc, char **argv)
{
// There can be only one....
if (find_port(SERVER_PORT_NAME) != B_NAME_NOT_FOUND)
return -1;
AppServer app_server;
app_server.Run();
return 0;
}