BAppServerLink is now using BApplication::fServerTo/From for its messaging.

Added LinkMsgReader::NeedsReply() method.
Completely redone ServerApp messaging: no more "replyport" from BAppServerLink; instead,
the registered client reply port is used. Fixed some more weak messaging stuff.
ServerApp now recognizes if an unknown message needs a reply, and sends it - for example,
the "Screen" preferences app no longer hangs, but crashes on start :)
Made LinkMsgReader::Read() virtual again, since it's needed by RAMLinkMsgReader.cpp.
Renamed BPortLink::GetNextReply() to GetNextMessage().
Some more cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13004 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2005-06-08 04:01:59 +00:00
parent be835bdf0b
commit bd28b3c746
12 changed files with 680 additions and 1033 deletions
+3 -1
View File
@@ -23,7 +23,9 @@ class LinkMsgReader {
port_id Port(void) { return fReceivePort; }
status_t GetNextMessage(int32 &code, bigtime_t timeout = B_INFINITE_TIMEOUT);
status_t Read(void *data, ssize_t size);
bool NeedsReply() const;
virtual status_t Read(void *data, ssize_t size);
status_t ReadString(char **string);
template <class Type> status_t Read(Type *data)
{
+11 -2
View File
@@ -61,7 +61,8 @@ class BPortLink {
void SetReplyPort(port_id port);
port_id ReplyPort();
status_t GetNextReply(int32 &code, bigtime_t timeout = B_INFINITE_TIMEOUT);
status_t GetNextMessage(int32 &code, bigtime_t timeout = B_INFINITE_TIMEOUT);
bool NeedsReply() const;
status_t Read(void *data, ssize_t size);
status_t ReadString(char **string);
status_t ReadRegion(BRegion *region);
@@ -71,6 +72,8 @@ class BPortLink {
// convenience methods
status_t FlushWithReply(int32 &code);
LinkMsgReader &Reader() { return *fReader; }
LinkMsgSender &Sender() { return *fSender; }
protected:
LinkMsgReader *fReader;
@@ -148,11 +151,17 @@ BPortLink::ReplyPort()
}
inline status_t
BPortLink::GetNextReply(int32 &code, bigtime_t timeout)
BPortLink::GetNextMessage(int32 &code, bigtime_t timeout)
{
return fReader->GetNextMessage(code, timeout);
}
inline bool
BPortLink::NeedsReply() const
{
return fReader->NeedsReply();
}
inline status_t
BPortLink::Read(void *data, ssize_t size)
{
+7 -19
View File
@@ -34,7 +34,6 @@
BLocker sLock;
port_id sReplyPort = -1;
namespace BPrivate {
@@ -44,15 +43,10 @@ BAppServerLink::BAppServerLink(void)
sLock.Lock();
// if there is no be_app, we can't do a whole lot, anyway
if (be_app)
if (be_app) {
SetSendPort(be_app->fServerFrom);
// There is only one global reply port, and we create it here
// (protected by sLock) when it's not yet there
if (sReplyPort < B_OK)
sReplyPort = create_port(100, "AppServerLink reply port");
SetReplyPort(sReplyPort);
SetReplyPort(be_app->fServerTo);
}
}
@@ -65,17 +59,11 @@ BAppServerLink::~BAppServerLink()
status_t
BAppServerLink::FlushWithReply(int32 *code)
{
status_t err;
err = Attach<port_id>(sReplyPort);
if (err < B_OK)
return err;
status_t status = Flush(B_INFINITE_TIMEOUT, true);
if (status < B_OK)
return status;
err = Flush();
if (err < B_OK)
return err;
return GetNextReply(*code);
return GetNextMessage(*code);
}
} // namespace BPrivate
+11
View File
@@ -102,6 +102,17 @@ LinkMsgReader::GetNextMessage(int32 &code, bigtime_t timeout)
}
bool
LinkMsgReader::NeedsReply() const
{
if (fReplySize == 0)
return false;
message_header *header = (message_header *)(fRecvBuffer + fRecvStart);
return (header->flags & kNeedsReply) != 0;
}
void
LinkMsgReader::ResetBuffer()
{
+2 -2
View File
@@ -92,9 +92,9 @@ BPortLink::AttachShape(BShape &shape)
status_t
BPortLink::FlushWithReply(int32 &code)
{
status_t status = Flush();
status_t status = Flush(B_INFINITE_TIMEOUT, true);
if (status < B_OK)
return status;
return GetNextReply(code);
return GetNextMessage(code);
}
+45 -54
View File
@@ -257,22 +257,16 @@ AppServer::~AppServer(void)
int32
AppServer::PicassoThread(void *data)
{
int32 i;
AppServer *appserver=(AppServer*)data;
ServerApp *app;
for(;;)
{
i = 0;
acquire_sem(appserver->fAppListLock);
for(;;)
{
app=(ServerApp*)appserver->fAppList->ItemAt(i++);
if(!app)
for (;;) {
acquire_sem(sAppServer->fAppListLock);
for (int32 i = 0;;) {
ServerApp *app = (ServerApp *)sAppServer->fAppList->ItemAt(i++);
if (!app)
break;
app->PingTarget();
}
release_sem(appserver->fAppListLock);
release_sem(sAppServer->fAppListLock);
// we do this every other second so as not to suck *too* many CPU cycles
snooze(1000000);
}
@@ -407,7 +401,7 @@ AppServer::MainLoop(void)
STRACE(("info: AppServer::MainLoop listening on port %ld.\n", fMessagePort));
int32 code;
status_t err = pmsg.GetNextReply(code);
status_t err = pmsg.GetNextMessage(code);
if (err < B_OK) {
STRACE(("MainLoop:pmsg.GetNextReply failed\n"));
continue;
@@ -424,12 +418,12 @@ AppServer::MainLoop(void)
case AS_SET_DECORATOR:
case AS_GET_DECORATOR:
case AS_R5_SET_DECORATOR:
DispatchMessage(code,pmsg);
DispatchMessage(code, pmsg);
break;
default:
{
STRACE(("Server::MainLoop received unexpected code %ld(offset %ld)\n",
code,code-SERVER_TRUE));
STRACE(("Server::MainLoop received unexpected code %ld (offset %ld)\n",
code, code - SERVER_TRUE));
break;
}
}
@@ -464,19 +458,19 @@ AppServer::LoadDecorator(const char *path)
status_t stat;
image_id addon;
addon= load_add_on(path);
if(addon < 0)
addon = load_add_on(path);
if (addon < B_OK)
return false;
// As of now, we do nothing with decorator versions, but the possibility exists
// that the API will change even though I cannot forsee any reason to do so. If
// we *did* do anything with decorator versions, the assignment to a global would
// go here.
// Get the instantiation function
stat= get_image_symbol(addon, "instantiate_decorator", B_SYMBOL_TYPE_TEXT, (void**)&pcreatefunc);
if(stat != B_OK)
{
stat = get_image_symbol(addon, "instantiate_decorator",
B_SYMBOL_TYPE_TEXT, (void**)&pcreatefunc);
if (stat != B_OK) {
unload_add_on(addon);
return false;
}
@@ -497,33 +491,29 @@ AppServer::InitDecorators(void)
{
BMessage settings;
BDirectory dir,newdir;
if(dir.SetTo(SERVER_SETTINGS_DIR)==B_ENTRY_NOT_FOUND)
create_directory(SERVER_SETTINGS_DIR,0777);
BDirectory dir;
if (dir.SetTo(SERVER_SETTINGS_DIR) == B_ENTRY_NOT_FOUND)
create_directory(SERVER_SETTINGS_DIR, 0777);
BString path(SERVER_SETTINGS_DIR);
path+="DecoratorSettings";
BFile file(path.String(),B_READ_ONLY);
path += "DecoratorSettings";
BFile file(path.String(), B_READ_ONLY);
if(file.InitCheck()==B_OK)
{
if(settings.Unflatten(&file)==B_OK)
{
BString itemtext;
if(settings.FindString("decorator",&itemtext)==B_OK)
{
path.SetTo(DECORATORS_DIR);
path+=itemtext;
if(LoadDecorator(path.String()))
return;
}
if (file.InitCheck() == B_OK
&& settings.Unflatten(&file) == B_OK) {
BString itemtext;
if (settings.FindString("decorator", &itemtext) == B_OK) {
path.SetTo(DECORATORS_DIR);
path += itemtext;
if (LoadDecorator(path.String()))
return;
}
}
// We got this far, so something must have gone wrong. We set make_decorator
// to NULL so that the decorator allocation routine knows to utilize the included
// default decorator instead of an addon.
make_decorator=NULL;
make_decorator = NULL;
}
/*!
@@ -550,25 +540,26 @@ AppServer::DispatchMessage(int32 code, BPortLink &msg)
// Find the necessary data
team_id clientTeamID = -1;
port_id clientLooperPort = -1;
port_id app_port = -1;
port_id clientReplyPort = -1;
int32 htoken = B_NULL_TOKEN;
char *app_signature = NULL;
char *appSignature = NULL;
msg.Read<port_id>(&app_port);
msg.Read<port_id>(&clientReplyPort);
msg.Read<port_id>(&clientLooperPort);
msg.Read<team_id>(&clientTeamID);
msg.Read<int32>(&htoken);
msg.ReadString(&app_signature);
if (msg.ReadString(&appSignature) != B_OK)
break;
port_id server_listen = create_port(DEFAULT_MONITOR_PORT_SIZE, app_signature);
if (server_listen < B_OK) {
port_id serverListen = create_port(DEFAULT_MONITOR_PORT_SIZE, appSignature);
if (serverListen < B_OK) {
printf("No more ports left. Time to crash. Have a nice day! :)\n");
break;
}
// we let the application own the port, so that we get aware when it's gone
if (set_port_owner(server_listen, clientTeamID) < B_OK) {
delete_port(server_listen);
if (set_port_owner(serverListen, clientTeamID) < B_OK) {
delete_port(serverListen);
printf("Could not transfer port ownership to client %ld!\n", clientTeamID);
break;
}
@@ -576,21 +567,21 @@ AppServer::DispatchMessage(int32 code, BPortLink &msg)
// Create the ServerApp subthread for this app
acquire_sem(fAppListLock);
ServerApp *app = new ServerApp(app_port,server_listen, clientLooperPort,
clientTeamID, htoken, app_signature);
ServerApp *app = new ServerApp(clientReplyPort, serverListen, clientLooperPort,
clientTeamID, htoken, appSignature);
// add the new ServerApp to the known list of ServerApps
fAppList->AddItem(app);
release_sem(fAppListLock);
BPortLink replylink(app_port);
BPortLink replylink(clientReplyPort);
replylink.StartMessage(SERVER_TRUE);
replylink.Attach<int32>(server_listen);
replylink.Attach<int32>(serverListen);
replylink.Flush();
// This is necessary because BPortLink::ReadString allocates memory
free(app_signature);
free(appSignature);
break;
}
case AS_DELETE_APP:
+15 -73
View File
@@ -25,8 +25,8 @@ RAMLinkMsgReader::~RAMLinkMsgReader(void)
}
void RAMLinkMsgReader::SetBuffer(int8 *buffer)
void
RAMLinkMsgReader::SetBuffer(int8 *buffer)
{
if(!buffer)
{
@@ -48,93 +48,35 @@ void RAMLinkMsgReader::SetBuffer(int8 *buffer)
}
int8 *RAMLinkMsgReader::GetBuffer(void)
int8 *
RAMLinkMsgReader::GetBuffer(void)
{
return fBuffer;
}
size_t RAMLinkMsgReader::GetBufferSize(void)
size_t
RAMLinkMsgReader::GetBufferSize(void)
{
return fAttachSize;
}
status_t RAMLinkMsgReader::Read(void *data, ssize_t size)
status_t
RAMLinkMsgReader::Read(void *data, ssize_t size)
{
if(!fBuffer || fAttachSize==0)
if (!fBuffer || fAttachSize == 0)
return B_NO_INIT;
if(size<1)
if (size < 1)
return B_BAD_VALUE;
if(fPosition+size > fAttachStart+fAttachSize)
{
if (fPosition + size > fAttachStart + fAttachSize) {
// read past end of buffer
return B_BAD_VALUE;
}
memcpy(data, fPosition, size);
fPosition+=size;
fPosition += size;
return B_OK;
}
status_t RAMLinkMsgReader::ReadString(char **string)
{
status_t err;
int32 len = 0;
err = Read<int32>(&len);
if (err < B_OK)
return err;
if (len)
{
*string = (char *)malloc(len);
if (*string == NULL)
{
fPosition -= sizeof(int32);
return B_NO_MEMORY;
}
err = Read(*string, len);
if (err < B_OK)
{
free(*string);
*string = NULL;
fPosition -= sizeof(int32);
return err;
}
(*string)[len-1] = '\0';
return B_OK;
}
else
{
fPosition -= sizeof(int32);
return B_ERROR;
}
}
// "Forbidden" functions :P
status_t RAMLinkMsgReader::GetNextMessage(int32 *code, bigtime_t timeout)
{
debugger("RAMLinkMsgReader::GetNextMessage is not permitted");
return B_ERROR;
}
void RAMLinkMsgReader::SetPort(port_id port)
{
debugger("RAMLinkMsgReader::SetPort is not permitted");
}
port_id RAMLinkMsgReader::GetPort(void)
{
debugger("RAMLinkMsgReader::GetPort is not permitted");
return B_ERROR;
}
+17 -31
View File
@@ -39,38 +39,24 @@
size_t buffer size
[data buffer]
*/
class RAMLinkMsgReader : public LinkMsgReader
{
public:
RAMLinkMsgReader(int8 *buffer);
RAMLinkMsgReader(void);
~RAMLinkMsgReader(void);
void SetBuffer(int8 *buffer);
int8 *GetBuffer(void);
size_t GetBufferSize(void);
int32 Code(void) { return fCode; }
status_t Read(void *data, ssize_t size);
status_t ReadString(char **string);
template <class Type> status_t Read(Type *data)
{
return Read(data, sizeof(Type));
}
class RAMLinkMsgReader : public LinkMsgReader {
public:
RAMLinkMsgReader(int8 *buffer);
RAMLinkMsgReader(void);
virtual ~RAMLinkMsgReader(void);
// These should never need to be called where this class is used. However, we do
// need to make debugging easier for such contexts...
status_t GetNextMessage(int32 *code, bigtime_t timeout);
void SetPort(port_id port);
port_id GetPort(void);
protected:
int8 *fBuffer, *fAttachStart;
int8 *fPosition;
size_t fAttachSize;
int32 fCode;
void SetBuffer(int8 *buffer);
int8 *GetBuffer(void);
size_t GetBufferSize(void);
int32 Code(void) { return fCode; }
virtual status_t Read(void *data, ssize_t size);
protected:
int8 *fBuffer, *fAttachStart;
int8 *fPosition;
size_t fAttachSize;
int32 fCode;
};
#endif
+1 -1
View File
@@ -208,7 +208,7 @@ RootLayer::WorkingThread(void *data)
STRACE(("info: RootLayer(%s)::WorkingThread listening on port %ld.\n", oneRootLayer->GetName(), oneRootLayer->fListenPort));
for (;;) {
err = messageQueue.GetNextReply(code);
err = messageQueue.GetNextMessage(code);
if (err < B_OK) {
STRACE(("WorkingThread: messageQueue.GetNextReply failed\n"));
continue;
File diff suppressed because it is too large Load Diff
+8 -10
View File
@@ -30,6 +30,7 @@
#include <OS.h>
#include <String.h>
#include <PortLink.h>
#include "FMWList.h"
@@ -38,8 +39,6 @@ class BMessage;
class BPortLink;
class BList;
class DisplayDriver;
class LinkMsgReader;
class LinkMsgSender;
class ServerPicture;
class ServerCursor;
class ServerBitmap;
@@ -92,9 +91,9 @@ public:
private:
void DispatchMessage(int32 code, LinkMsgReader &link);
static int32 MonitorApp(void *data);
// our BApplication's event port
port_id fClientAppPort;
// port we receive messages from our BApplication
@@ -104,15 +103,14 @@ private:
// 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;
BString fSignature;
thread_id fMonitorThreadID;
team_id fClientTeamID;
LinkMsgReader *fMsgReader;
LinkMsgSender *fMsgSender;
BPortLink fLink;
// 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 ?
@@ -12,7 +12,7 @@ void
get_next_message(BPortLink &link, int32 expectedCode)
{
int32 code;
if (link.GetNextReply(code) != B_OK) {
if (link.GetNextMessage(code) != B_OK) {
fprintf(stderr, "get message failed!\n");
exit(-1);
}
@@ -96,7 +96,7 @@ main()
get_next_message(receiver, 'tst5');
int32 code;
status = receiver.GetNextReply(code, 0);
status = receiver.GetNextMessage(code, 0);
if (status != B_WOULD_BLOCK) {
fprintf(stderr, "reading would not block!\n");
return -1;