Added app flags related tests. Fixed some problems: LaunchContext doesn't have a LaunchCaller as member anymore, team = NULL parameter for BRoster::Launch() is now handled gracefully.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1370 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -256,6 +256,67 @@ case 13:mimeType is installed, but has no preferred application,
|
||||
case 14:installed type mimeType, preferred app, app type not installed,
|
||||
app has signature, app is trash =>
|
||||
Should return B_LAUNCH_FAILED_APP_IN_TRASH.
|
||||
case 15:installed type mimeType, preferred app, app type not installed,
|
||||
app has signature, team is NULL =>
|
||||
Should return B_OK and set team to the ID of the team running the
|
||||
application's executable. Should install the app type and set the
|
||||
app hint on it.
|
||||
|
||||
case 16:launch the app two times: B_MULTIPLE_LAUNCH | B_ARGV_ONLY =>
|
||||
first app: ArgvReceived(), ReadyToRun(), QuitRequested()
|
||||
second app: ArgvReceived(), ReadyToRun(), QuitRequested()
|
||||
case 17:launch the app two times: B_MULTIPLE_LAUNCH =>
|
||||
first app: {Message,Argv,Refs}Received()*, ReadyToRun(),
|
||||
QuitRequested()
|
||||
second app: {Message,Argv,Refs}Received()*, ReadyToRun(),
|
||||
QuitRequested()
|
||||
case 18:launch the app two times: B_SINGLE_LAUNCH | B_ARGV_ONLY =>
|
||||
first app: ArgvReceived(), ReadyToRun(), QuitRequested()
|
||||
(No second ArgvReceived()!)
|
||||
second app: Launch() fails with B_ALREADY_RUNNING
|
||||
case 19:launch the app two times: B_SINGLE_LAUNCH =>
|
||||
first app: {Message,Argv,Refs}Received()*, ReadyToRun(),
|
||||
{Message,Argv,Refs}Received()*, QuitRequested()
|
||||
second app: Launch() fails with B_ALREADY_RUNNING
|
||||
case 20:launch two apps with the same signature:
|
||||
B_SINGLE_LAUNCH | B_ARGV_ONLY =>
|
||||
first app: ArgvReceived(), ReadyToRun(), QuitRequested()
|
||||
second app: ArgvReceived(), ReadyToRun(), QuitRequested()
|
||||
case 21:launch two apps with the same signature: B_SINGLE_LAUNCH =>
|
||||
first app: {Message,Argv,Refs}Received()*, ReadyToRun(),
|
||||
QuitRequested()
|
||||
second app: {Message,Argv,Refs}Received()*, ReadyToRun(),
|
||||
QuitRequested()
|
||||
case 22:launch the app two times: B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY =>
|
||||
first app: ArgvReceived(), ReadyToRun(), QuitRequested()
|
||||
(No second ArgvReceived()!)
|
||||
second app: Launch() fails with B_ALREADY_RUNNING
|
||||
case 23:launch the app two times: B_EXCLUSIVE_LAUNCH =>
|
||||
first app: {Message,Argv,Refs}Received()*, ReadyToRun(),
|
||||
{Message,Argv,Refs}Received()*, QuitRequested()
|
||||
second app: Launch() fails with B_ALREADY_RUNNING
|
||||
case 24:launch two apps with the same signature:
|
||||
B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY =>
|
||||
first app: ArgvReceived(), ReadyToRun(), QuitRequested()
|
||||
(No second ArgvReceived()!)
|
||||
second app: Launch() fails with B_ALREADY_RUNNING
|
||||
case 25:launch two apps with the same signature: B_EXCLUSIVE_LAUNCH =>
|
||||
first app: {Message,Argv,Refs}Received()*, ReadyToRun(),
|
||||
{Message,Argv,Refs}Received()*, QuitRequested()
|
||||
second app: Launch() fails with B_ALREADY_RUNNING
|
||||
case 26:launch two apps with the same signature:
|
||||
first: B_EXCLUSIVE_LAUNCH,
|
||||
second: B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY =>
|
||||
first app: {Message,Argv,Refs}Received()*, ReadyToRun(),
|
||||
QuitRequested()
|
||||
second app: Launch() fails with B_ALREADY_RUNNING
|
||||
case 27:launch two apps with the same signature:
|
||||
first: B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY,
|
||||
second: B_EXCLUSIVE_LAUNCH =>
|
||||
first app: ArgvReceived(), ReadyToRun(), QuitRequested()
|
||||
(No second ArgvReceived()!)
|
||||
second app: Launch() fails with B_ALREADY_RUNNING
|
||||
|
||||
|
||||
status_t Launch(const char *mimeType, BMessage *initialMsg,
|
||||
team_id *appTeam) const
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,6 +29,40 @@ public:
|
||||
bigtime_t when;
|
||||
};
|
||||
|
||||
// Sleeper
|
||||
class LaunchContext::Sleeper {
|
||||
public:
|
||||
Sleeper() : fMessageCode(0), fSemaphore(-1) {}
|
||||
|
||||
~Sleeper()
|
||||
{
|
||||
delete_sem(fSemaphore);
|
||||
}
|
||||
|
||||
status_t Init(uint32 messageCode)
|
||||
{
|
||||
fMessageCode = messageCode;
|
||||
fSemaphore = create_sem(0, "sleeper sem");
|
||||
return (fSemaphore >= 0 ? B_OK : fSemaphore);
|
||||
}
|
||||
|
||||
uint32 MessageCode() const { return fMessageCode; }
|
||||
|
||||
status_t Sleep(bigtime_t timeout = B_INFINITE_TIMEOUT)
|
||||
{
|
||||
return acquire_sem_etc(fSemaphore, 1, B_RELATIVE_TIMEOUT, timeout);
|
||||
}
|
||||
|
||||
status_t WakeUp()
|
||||
{
|
||||
return release_sem(fSemaphore);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 fMessageCode;
|
||||
sem_id fSemaphore;
|
||||
};
|
||||
|
||||
// AppInfo
|
||||
class LaunchContext::AppInfo {
|
||||
public:
|
||||
@@ -76,6 +110,7 @@ public:
|
||||
message->message = _message;
|
||||
message->when = system_time();
|
||||
fMessages.AddItem(message);
|
||||
NotifySleepers(_message.what);
|
||||
}
|
||||
|
||||
LaunchContext::Message *RemoveMessage(int32 index)
|
||||
@@ -88,17 +123,49 @@ public:
|
||||
return (LaunchContext::Message*)fMessages.ItemAt(index);
|
||||
}
|
||||
|
||||
LaunchContext::Message *FindMessage(uint32 messageCode,
|
||||
int32 startIndex = 0) const
|
||||
{
|
||||
LaunchContext::Message *message = NULL;
|
||||
for (int32 i = startIndex; (message = MessageAt(i)) != NULL; i++) {
|
||||
if (message->message.what == messageCode)
|
||||
break;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
void AddSleeper(Sleeper *sleeper)
|
||||
{
|
||||
fSleepers.AddItem(sleeper);
|
||||
}
|
||||
|
||||
void RemoveSleeper(Sleeper *sleeper)
|
||||
{
|
||||
fSleepers.RemoveItem(sleeper);
|
||||
}
|
||||
|
||||
void NotifySleepers(uint32 messageCode)
|
||||
{
|
||||
for (int32 i = 0;
|
||||
Sleeper *sleeper = (Sleeper*)fSleepers.ItemAt(i);
|
||||
i++) {
|
||||
if (sleeper->MessageCode() == messageCode)
|
||||
sleeper->WakeUp();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
team_id fTeam;
|
||||
BMessenger fMessenger;
|
||||
BList fMessages;
|
||||
bool fTerminating;
|
||||
BList fSleepers;
|
||||
};
|
||||
|
||||
// constructor
|
||||
LaunchContext::LaunchContext(LaunchCaller &caller)
|
||||
: fCaller(caller),
|
||||
fAppInfos(),
|
||||
LaunchContext::LaunchContext()
|
||||
: fAppInfos(),
|
||||
fSleepers(),
|
||||
fLock(),
|
||||
fAppThread(B_ERROR),
|
||||
fTerminator(B_ERROR),
|
||||
@@ -133,7 +200,8 @@ LaunchContext::~LaunchContext()
|
||||
|
||||
// ()
|
||||
status_t
|
||||
LaunchContext::operator()(const char *type, team_id *team)
|
||||
LaunchContext::operator()(LaunchCaller &caller, const char *type,
|
||||
team_id *team)
|
||||
{
|
||||
BMessage message1(MSG_1);
|
||||
BMessage message2(MSG_2);
|
||||
@@ -142,28 +210,20 @@ LaunchContext::operator()(const char *type, team_id *team)
|
||||
messages.AddItem(&message1);
|
||||
messages.AddItem(&message2);
|
||||
messages.AddItem(&message3);
|
||||
return (*this)(type, &messages, kStandardArgc, kStandardArgv, team);
|
||||
return (*this)(caller, type, &messages, kStandardArgc, kStandardArgv,
|
||||
team);
|
||||
}
|
||||
|
||||
// ()
|
||||
status_t
|
||||
LaunchContext::operator()(const char *type, BList *messages, int32 argc,
|
||||
const char **argv, team_id *team)
|
||||
LaunchContext::operator()(LaunchCaller &caller, const char *type,
|
||||
BList *messages, int32 argc, const char **argv,
|
||||
team_id *team)
|
||||
{
|
||||
BAutolock _lock(fLock);
|
||||
status_t result = fCaller(type, messages, argc, argv, team);
|
||||
if (result == B_OK) {
|
||||
if (team)
|
||||
CreateAppInfo(*team);
|
||||
else {
|
||||
// Note: Here's a race condition. If Terminate() is called, before
|
||||
// we've received the first message from the test app, then
|
||||
// there's a good chance that we quit the application before
|
||||
// having received any message (or at least not all messages)
|
||||
// from the test app. We wait some time to minimize the chance...
|
||||
snooze(100000);
|
||||
}
|
||||
}
|
||||
status_t result = caller(type, messages, argc, argv, team);
|
||||
if (result == B_OK && team)
|
||||
CreateAppInfo(*team);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -173,6 +233,14 @@ LaunchContext::HandleMessage(BMessage *message)
|
||||
{
|
||||
//printf("LaunchContext::HandleMessage(%6ld: %.4s)\n",
|
||||
//message->ReturnAddress().Team(), (char*)&message->what);
|
||||
//if (message->what == MSG_MESSAGE_RECEIVED) {
|
||||
// BMessage sentMessage;
|
||||
// message->FindMessage("message", &sentMessage);
|
||||
// team_id sender = -1;
|
||||
// message->FindInt32("sender", &sender);
|
||||
// printf(" <- %6ld: %.4s\n", sender, (char*)&sentMessage.what);
|
||||
//}
|
||||
|
||||
BAutolock _lock(fLock);
|
||||
switch (message->what) {
|
||||
case MSG_STARTED:
|
||||
@@ -184,10 +252,20 @@ LaunchContext::HandleMessage(BMessage *message)
|
||||
case MSG_READY_TO_RUN:
|
||||
{
|
||||
BMessenger messenger = message->ReturnAddress();
|
||||
AppInfo *info = CreateAppInfo(messenger);
|
||||
info->AddMessage(*message);
|
||||
if (fTerminating)
|
||||
TerminateApp(info);
|
||||
// add the message to the respective team's message list
|
||||
// Note: catch messages that have not been sent by us or the
|
||||
// remote team. The R5 registrar seems to send a B_REPLY message
|
||||
// sometimes.
|
||||
team_id sender = -1;
|
||||
if (message->FindInt32("sender", &sender) != B_OK
|
||||
|| sender == be_app->Team()
|
||||
|| sender == messenger.Team()) {
|
||||
AppInfo *info = CreateAppInfo(messenger);
|
||||
info->AddMessage(*message);
|
||||
if (fTerminating)
|
||||
TerminateApp(info);
|
||||
}
|
||||
NotifySleepers(message->what);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -252,7 +330,8 @@ LaunchContext::NextMessageFrom(team_id team, int32 &cookie, bigtime_t *time)
|
||||
|
||||
// CheckNextMessage
|
||||
bool
|
||||
LaunchContext::CheckNextMessage(team_id team, int32 &cookie, uint32 what)
|
||||
LaunchContext::CheckNextMessage(LaunchCaller &caller, team_id team,
|
||||
int32 &cookie, uint32 what)
|
||||
{
|
||||
BMessage *message = NextMessageFrom(team, cookie);
|
||||
return (message && message->what == what);
|
||||
@@ -260,12 +339,13 @@ LaunchContext::CheckNextMessage(team_id team, int32 &cookie, uint32 what)
|
||||
|
||||
// CheckArgvMessage
|
||||
bool
|
||||
LaunchContext::CheckArgvMessage(team_id team, int32 &cookie,
|
||||
const entry_ref *appRef, bool useRef)
|
||||
LaunchContext::CheckArgvMessage(LaunchCaller &caller, team_id team,
|
||||
int32 &cookie, const entry_ref *appRef,
|
||||
bool useRef)
|
||||
{
|
||||
bool result = true;
|
||||
if (fCaller.SupportsArgv()) {
|
||||
result = CheckArgvMessage(team, cookie, appRef, kStandardArgc,
|
||||
if (caller.SupportsArgv()) {
|
||||
result = CheckArgvMessage(caller, team, cookie, appRef, kStandardArgc,
|
||||
kStandardArgv, useRef);
|
||||
}
|
||||
return result;
|
||||
@@ -273,18 +353,18 @@ LaunchContext::CheckArgvMessage(team_id team, int32 &cookie,
|
||||
|
||||
// CheckArgvMessage
|
||||
bool
|
||||
LaunchContext::CheckArgvMessage(team_id team, int32 &cookie,
|
||||
const entry_ref *appRef, int32 argc,
|
||||
const char **argv, bool useRef)
|
||||
LaunchContext::CheckArgvMessage(LaunchCaller &caller, team_id team,
|
||||
int32 &cookie, const entry_ref *appRef,
|
||||
int32 argc, const char **argv, bool useRef)
|
||||
{
|
||||
const entry_ref *ref = (useRef ? fCaller.Ref() : NULL);
|
||||
return CheckArgvMessage(team, cookie, appRef, ref , argc, argv);
|
||||
const entry_ref *ref = (useRef ? caller.Ref() : NULL);
|
||||
return CheckArgvMessage(caller, team, cookie, appRef, ref , argc, argv);
|
||||
}
|
||||
|
||||
// CheckArgvMessage
|
||||
bool
|
||||
LaunchContext::CheckArgvMessage(team_id team, int32 &cookie,
|
||||
const entry_ref *appRef,
|
||||
LaunchContext::CheckArgvMessage(LaunchCaller &caller, team_id team,
|
||||
int32 &cookie, const entry_ref *appRef,
|
||||
const entry_ref *ref , int32 argc,
|
||||
const char **argv)
|
||||
{
|
||||
@@ -330,62 +410,36 @@ printf("app paths differ: `%s' vs `%s'\n", arg, path.Path());
|
||||
return result;
|
||||
}
|
||||
|
||||
// RemoveStandardArgvMessage
|
||||
bool
|
||||
LaunchContext::RemoveStandardArgvMessage(team_id team, const entry_ref *appRef)
|
||||
{
|
||||
return RemoveArgvMessage(team, appRef, kStandardArgc, kStandardArgv);
|
||||
}
|
||||
|
||||
// RemoveArgvMessage
|
||||
bool
|
||||
LaunchContext::RemoveArgvMessage(team_id team, const entry_ref *appRef,
|
||||
int32 argc, const char **argv)
|
||||
{
|
||||
BAutolock _lock(fLock);
|
||||
bool result = true;
|
||||
if (fCaller.SupportsArgv()) {
|
||||
result = false;
|
||||
int32 cookie = 0;
|
||||
while (BMessage *message = NextMessageFrom(team, cookie)) {
|
||||
if (message->what == MSG_ARGV_RECEIVED) {
|
||||
int32 index = --cookie;
|
||||
result = CheckArgvMessage(team, cookie, appRef, argc, argv);
|
||||
delete AppInfoFor(team)->RemoveMessage(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// CheckMessageMessages
|
||||
bool
|
||||
LaunchContext::CheckMessageMessages(team_id team, int32 &cookie)
|
||||
LaunchContext::CheckMessageMessages(LaunchCaller &caller, team_id team,
|
||||
int32 &cookie)
|
||||
{
|
||||
BAutolock _lock(fLock);
|
||||
bool result = true;
|
||||
for (int32 i = 0; i < 3; i++)
|
||||
result &= CheckMessageMessage(team, cookie, i);
|
||||
result &= CheckMessageMessage(caller, team, cookie, i);
|
||||
return result;
|
||||
}
|
||||
|
||||
// CheckMessageMessage
|
||||
bool
|
||||
LaunchContext::CheckMessageMessage(team_id team, int32 &cookie, int32 index)
|
||||
LaunchContext::CheckMessageMessage(LaunchCaller &caller, team_id team,
|
||||
int32 &cookie, int32 index)
|
||||
{
|
||||
bool result = true;
|
||||
if (fCaller.SupportsMessages() > index && index < 3) {
|
||||
if (caller.SupportsMessages() > index && index < 3) {
|
||||
uint32 commands[] = { MSG_1, MSG_2, MSG_3 };
|
||||
BMessage message(commands[index]);
|
||||
result = CheckMessageMessage(team, cookie, &message);
|
||||
result = CheckMessageMessage(caller, team, cookie, &message);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// CheckMessageMessage
|
||||
bool
|
||||
LaunchContext::CheckMessageMessage(team_id team, int32 &cookie,
|
||||
LaunchContext::CheckMessageMessage(LaunchCaller &caller, team_id team,
|
||||
int32 &cookie,
|
||||
const BMessage *expectedMessage)
|
||||
{
|
||||
BMessage *message = NextMessageFrom(team, cookie);
|
||||
@@ -400,18 +454,20 @@ LaunchContext::CheckMessageMessage(team_id team, int32 &cookie,
|
||||
|
||||
// CheckRefsMessage
|
||||
bool
|
||||
LaunchContext::CheckRefsMessage(team_id team, int32 &cookie)
|
||||
LaunchContext::CheckRefsMessage(LaunchCaller &caller, team_id team,
|
||||
int32 &cookie)
|
||||
{
|
||||
bool result = true;
|
||||
if (fCaller.SupportsRefs())
|
||||
result = CheckRefsMessage(team, cookie, fCaller.Ref());
|
||||
if (caller.SupportsRefs())
|
||||
result = CheckRefsMessage(caller, team, cookie, caller.Ref());
|
||||
return result;
|
||||
}
|
||||
|
||||
// CheckRefsMessage
|
||||
bool
|
||||
LaunchContext::CheckRefsMessage(team_id team, int32 &cookie,
|
||||
const entry_ref *refs, int32 count)
|
||||
LaunchContext::CheckRefsMessage(LaunchCaller &caller, team_id team,
|
||||
int32 &cookie, const entry_ref *refs,
|
||||
int32 count)
|
||||
{
|
||||
BMessage *message = NextMessageFrom(team, cookie);
|
||||
bool result = (message && message->what == MSG_REFS_RECEIVED);
|
||||
@@ -425,25 +481,60 @@ LaunchContext::CheckRefsMessage(team_id team, int32 &cookie,
|
||||
return result;
|
||||
}
|
||||
|
||||
// RemoveRefsMessage
|
||||
// WaitForMessage
|
||||
bool
|
||||
LaunchContext::RemoveRefsMessage(team_id team)
|
||||
LaunchContext::WaitForMessage(uint32 messageCode, bool fromNow,
|
||||
bigtime_t timeout)
|
||||
{
|
||||
BAutolock _lock(fLock);
|
||||
bool result = true;
|
||||
if (fCaller.SupportsRefs()) {
|
||||
result = false;
|
||||
int32 cookie = 0;
|
||||
while (BMessage *message = NextMessageFrom(team, cookie)) {
|
||||
if (message->what == MSG_REFS_RECEIVED) {
|
||||
int32 index = --cookie;
|
||||
result = CheckRefsMessage(team, cookie);
|
||||
delete AppInfoFor(team)->RemoveMessage(index);
|
||||
break;
|
||||
status_t error = B_ERROR;
|
||||
fLock.Lock();
|
||||
error = B_OK;
|
||||
if (fromNow || !FindMessage(messageCode)) {
|
||||
// add sleeper
|
||||
Sleeper *sleeper = new Sleeper;
|
||||
error = sleeper->Init(messageCode);
|
||||
if (error == B_OK) {
|
||||
AddSleeper(sleeper);
|
||||
fLock.Unlock();
|
||||
// sleep
|
||||
error = sleeper->Sleep(timeout);
|
||||
fLock.Lock();
|
||||
// remove sleeper
|
||||
RemoveSleeper(sleeper);
|
||||
delete sleeper;
|
||||
}
|
||||
}
|
||||
fLock.Unlock();
|
||||
return (error == B_OK);
|
||||
}
|
||||
|
||||
// WaitForMessage
|
||||
bool
|
||||
LaunchContext::WaitForMessage(team_id team, uint32 messageCode, bool fromNow,
|
||||
bigtime_t timeout)
|
||||
{
|
||||
status_t error = B_ERROR;
|
||||
fLock.Lock();
|
||||
if (AppInfo *info = AppInfoFor(team)) {
|
||||
error = B_OK;
|
||||
if (fromNow || !info->FindMessage(messageCode)) {
|
||||
// add sleeper
|
||||
Sleeper *sleeper = new Sleeper;
|
||||
error = sleeper->Init(messageCode);
|
||||
if (error == B_OK) {
|
||||
info->AddSleeper(sleeper);
|
||||
fLock.Unlock();
|
||||
// sleep
|
||||
error = sleeper->Sleep(timeout);
|
||||
fLock.Lock();
|
||||
// remove sleeper
|
||||
info->RemoveSleeper(sleeper);
|
||||
delete sleeper;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
fLock.Unlock();
|
||||
return (error == B_OK);
|
||||
}
|
||||
|
||||
// StandardMessages
|
||||
@@ -541,6 +632,42 @@ LaunchContext::TerminatorEntry(void *data)
|
||||
return ((LaunchContext*)data)->Terminator();
|
||||
}
|
||||
|
||||
// FindMessage
|
||||
LaunchContext::Message*
|
||||
LaunchContext::FindMessage(uint32 messageCode)
|
||||
{
|
||||
BAutolock _lock(fLock);
|
||||
Message *message = NULL;
|
||||
AppInfo *info = NULL;
|
||||
for (int32 i = 0; !message && (info = AppInfoAt(i)) != NULL; i++)
|
||||
message = info->FindMessage(messageCode);
|
||||
return message;
|
||||
}
|
||||
|
||||
// AddSleeper
|
||||
void
|
||||
LaunchContext::AddSleeper(Sleeper *sleeper)
|
||||
{
|
||||
fSleepers.AddItem(sleeper);
|
||||
}
|
||||
|
||||
// RemoveSleeper
|
||||
void
|
||||
LaunchContext::RemoveSleeper(Sleeper *sleeper)
|
||||
{
|
||||
fSleepers.RemoveItem(sleeper);
|
||||
}
|
||||
|
||||
// NotifySleepers
|
||||
void
|
||||
LaunchContext::NotifySleepers(uint32 messageCode)
|
||||
{
|
||||
for (int32 i = 0; Sleeper *sleeper = (Sleeper*)fSleepers.ItemAt(i); i++) {
|
||||
if (sleeper->MessageCode() == messageCode)
|
||||
sleeper->WakeUp();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////
|
||||
// RosterLaunchApp
|
||||
|
||||
@@ -18,23 +18,40 @@ enum {
|
||||
// LaunchCaller
|
||||
class LaunchCaller {
|
||||
public:
|
||||
LaunchCaller() : fNext(NULL) {}
|
||||
virtual ~LaunchCaller() { if (fNext) delete fNext;}
|
||||
|
||||
virtual status_t operator()(const char *type, BList *messages, int32 argc,
|
||||
const char **argv, team_id *team) = 0;
|
||||
virtual int32 SupportsMessages() const { return 1; }
|
||||
virtual bool SupportsArgv() const { return SupportsMessages() == 0; }
|
||||
virtual bool SupportsRefs() const { return false; }
|
||||
virtual const entry_ref *Ref() const { return NULL; }
|
||||
|
||||
virtual LaunchCaller &Clone()
|
||||
{
|
||||
LaunchCaller *newCaller = CloneInternal();
|
||||
newCaller->fNext = fNext;
|
||||
fNext = newCaller;
|
||||
return *newCaller;
|
||||
}
|
||||
|
||||
virtual LaunchCaller *CloneInternal() = 0;
|
||||
|
||||
private:
|
||||
LaunchCaller *fNext;
|
||||
};
|
||||
|
||||
// LaunchContext
|
||||
class LaunchContext {
|
||||
public:
|
||||
LaunchContext(LaunchCaller &caller);
|
||||
LaunchContext();
|
||||
~LaunchContext();
|
||||
|
||||
status_t operator()(const char *type, team_id *team);
|
||||
status_t operator()(const char *type, BList *messages, int32 argc,
|
||||
const char **argv, team_id *team);
|
||||
status_t operator()(LaunchCaller &caller, const char *type, team_id *team);
|
||||
status_t operator()(LaunchCaller &caller, const char *type,
|
||||
BList *messages, int32 argc, const char **argv,
|
||||
team_id *team);
|
||||
|
||||
void HandleMessage(BMessage *message);
|
||||
|
||||
@@ -44,24 +61,30 @@ public:
|
||||
|
||||
BMessage *NextMessageFrom(team_id team, int32 &cookie,
|
||||
bigtime_t *time = NULL);
|
||||
bool CheckNextMessage(team_id team, int32 &cookie, uint32 what);
|
||||
bool CheckArgvMessage(team_id team, int32 &cookie,
|
||||
bool CheckNextMessage(LaunchCaller &caller, team_id team, int32 &cookie,
|
||||
uint32 what);
|
||||
bool CheckArgvMessage(LaunchCaller &caller, team_id team, int32 &cookie,
|
||||
const entry_ref *appRef, bool useRef = true);
|
||||
bool CheckArgvMessage(team_id team, int32 &cookie, const entry_ref *appRef,
|
||||
bool CheckArgvMessage(LaunchCaller &caller, team_id team, int32 &cookie,
|
||||
const entry_ref *appRef,
|
||||
int32 argc, const char **argv, bool useRef = true);
|
||||
bool CheckArgvMessage(team_id team, int32 &cookie, const entry_ref *appRef,
|
||||
const entry_ref *ref, int32 argc, const char **argv);
|
||||
bool RemoveStandardArgvMessage(team_id team, const entry_ref *appRef);
|
||||
bool RemoveArgvMessage(team_id team, const entry_ref *appRef, int32 argc,
|
||||
const char **argv);
|
||||
bool CheckMessageMessages(team_id team, int32 &cookie);
|
||||
bool CheckMessageMessage(team_id team, int32 &cookie, int32 index);
|
||||
bool CheckMessageMessage(team_id team, int32 &cookie,
|
||||
bool CheckArgvMessage(LaunchCaller &caller, team_id team, int32 &cookie,
|
||||
const entry_ref *appRef, const entry_ref *ref,
|
||||
int32 argc, const char **argv);
|
||||
bool CheckMessageMessages(LaunchCaller &caller, team_id team,
|
||||
int32 &cookie);
|
||||
bool CheckMessageMessage(LaunchCaller &caller, team_id team, int32 &cookie,
|
||||
int32 index);
|
||||
bool CheckMessageMessage(LaunchCaller &caller, team_id team, int32 &cookie,
|
||||
const BMessage *message);
|
||||
bool CheckRefsMessage(team_id team, int32 &cookie);
|
||||
bool CheckRefsMessage(team_id team, int32 &cookie, const entry_ref *refs,
|
||||
int32 count = 1);
|
||||
bool RemoveRefsMessage(team_id team);
|
||||
bool CheckRefsMessage(LaunchCaller &caller, team_id team, int32 &cookie);
|
||||
bool CheckRefsMessage(LaunchCaller &caller, team_id team, int32 &cookie,
|
||||
const entry_ref *refs, int32 count = 1);
|
||||
|
||||
bool WaitForMessage(uint32 messageCode, bool fromNow = false,
|
||||
bigtime_t timeout = B_INFINITE_TIMEOUT);
|
||||
bool WaitForMessage(team_id team, uint32 messageCode, bool fromNow = false,
|
||||
bigtime_t timeout = B_INFINITE_TIMEOUT);
|
||||
|
||||
BList *StandardMessages();
|
||||
|
||||
@@ -71,6 +94,7 @@ public:
|
||||
|
||||
private:
|
||||
class Message;
|
||||
class Sleeper;
|
||||
class AppInfo;
|
||||
|
||||
private:
|
||||
@@ -80,14 +104,19 @@ private:
|
||||
AppInfo *CreateAppInfo(BMessenger messenger);
|
||||
void TerminateApp(AppInfo *info);
|
||||
|
||||
Message *FindMessage(uint32 messageCode);
|
||||
void AddSleeper(Sleeper *sleeper);
|
||||
void RemoveSleeper(Sleeper *sleeper);
|
||||
void NotifySleepers(uint32 messageCode);
|
||||
|
||||
int32 Terminator();
|
||||
|
||||
static int32 AppThreadEntry(void *data);
|
||||
static int32 TerminatorEntry(void *data);
|
||||
|
||||
private:
|
||||
LaunchCaller &fCaller;
|
||||
BList fAppInfos;
|
||||
BList fSleepers;
|
||||
mutable BLocker fLock;
|
||||
thread_id fAppThread;
|
||||
thread_id fTerminator;
|
||||
|
||||
Reference in New Issue
Block a user