Skip to content

Commit

Permalink
Debugger: Rework to fully use TargetHostInterface.
Browse files Browse the repository at this point in the history
Application objects:
- Rework and simplify to take into account that they will no longer be
  directly managing the team debugger list. Requests to start a new debugger
  are still funnelled through here however, and as such, said requests must
  now provide the appropriate target host to start with. Adjust StartTeamWindow
  and TeamsWindow accordingly.
- On global init, always create an instance of the local interface.

TargetHostInterface:
- Convert to BLooper and implement TeamDebugger's Listener interface.
  TargetHostInterfaces now directly manage their TeamDebugger instances,
  and consequently take over the equivalent duties that the main application
  previously had.
- Adjust signatures of Attach/CreateTeam to add const. Adjust
  LocalTargetHostInterface accordingly.
- Add accessor to determine if a given interface is local or not. Will be
  needed for the TeamDebugger's file manager eventually so it knows if it
  needs to request remote files if no matching local file is found.
- Add accessor to start a TeamDebugger instance, and corresponding options
  structure.

TargetHostInterfaceRoster:
- Minor adjustments to host interface initialization to take into account
  needing to start the looper.
- Add accessor for number of running team debuggers, for the main app to
  use when deciding to quit.

TeamDebugger:
- Add accessor for SettingsManager. Needed for the case of a restart request,
  as the host interfaces do not have direct access to it.

TeamsWindow:
- For now, always grab the local host interface when initializing the window.
  Once the remote interface is implemented, this will need to be adjusted, but
  the appropriate UI for creating/selecting it is needed first anyways.

With these changes, the main application is fully host-agnostic, and all
management of actual debuggers is delegated to their parent host interfaces.
There still needs to be a listener interface for the host interface and/or
roster though, so that the application can be made aware of when debuggers
quit, as this drives whether it's time to terminate the app or not.
  • Loading branch information
anevilyak committed Apr 21, 2016
1 parent 52da202 commit a1afac4
Show file tree
Hide file tree
Showing 13 changed files with 405 additions and 381 deletions.
437 changes: 99 additions & 338 deletions src/apps/debugger/Debugger.cpp

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/apps/debugger/controllers/TeamDebugger.h
Expand Up @@ -55,6 +55,8 @@ class TeamDebugger : public BLooper, private UserInterfaceListener,
{ return fCommandLineArgc; }
const char** Arguments() const
{ return fCommandLineArgv; }
SettingsManager* GetSettingsManager() const
{ return fSettingsManager; }

virtual void MessageReceived(BMessage* message);

Expand Down
190 changes: 186 additions & 4 deletions src/apps/debugger/target_host_interface/TargetHostInterface.cpp
Expand Up @@ -5,12 +5,37 @@

#include "TargetHostInterface.h"

#include <stdio.h>

#include <AutoLocker.h>

#include "DebuggerInterface.h"
#include "GraphicalUserInterface.h"
#include "MessageCodes.h"
#include "TeamDebugger.h"


// #pragma mark - TeamDebuggerOptions


TeamDebuggerOptions::TeamDebuggerOptions()
:
commandLineArgc(0),
commandLineArgv(NULL),
team(-1),
thread(-1),
settingsManager(NULL),
userInterface(NULL)
{
}


// #pragma mark - TargetHostInterface


TargetHostInterface::TargetHostInterface()
:
BReferenceable(),
BLooper(),
fTeamDebuggers(20, false)
{
}
Expand All @@ -21,10 +46,40 @@ TargetHostInterface::~TargetHostInterface()
}


void
TargetHostInterface::SetName(const BString& name)
status_t
TargetHostInterface::StartTeamDebugger(const TeamDebuggerOptions& options)
{
fName = name;
// we only want to stop in main for teams we're responsible for
// creating ourselves.
bool stopInMain = options.commandLineArgv != NULL;
team_id team = options.team;
thread_id thread = options.thread;

AutoLocker<TargetHostInterface> interfaceLocker(this);
if (options.commandLineArgc > 0) {
status_t error = CreateTeam(options.commandLineArgc,
options.commandLineArgv, team);
if (error != B_OK)
return error;
thread = team;
}

if (team < 0 && thread < 0)
return B_BAD_VALUE;

if (team < 0) {
status_t error = FindTeamByThread(thread, team);
if (error != B_OK)
return error;
}

TeamDebugger* debugger = FindTeamDebugger(team);
if (debugger != NULL) {
debugger->Activate();
return B_OK;
}

return _StartTeamDebugger(team, options, stopInMain);
}


Expand Down Expand Up @@ -69,6 +124,133 @@ TargetHostInterface::RemoveTeamDebugger(TeamDebugger* debugger)
}


void
TargetHostInterface::Quit()
{
if (fTeamDebuggers.CountItems() == 0)
BLooper::Quit();
}


void
TargetHostInterface::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_TEAM_DEBUGGER_QUIT:
{
thread_id thread;
if (message->FindInt32("thread", &thread) == B_OK)
wait_for_thread(thread, NULL);
break;
}
case MSG_TEAM_RESTART_REQUESTED:
{
int32 teamID;
if (message->FindInt32("team", &teamID) != B_OK)
break;

TeamDebugger* debugger = FindTeamDebugger(teamID);

TeamDebuggerOptions options;
options.commandLineArgc = debugger->ArgumentCount();
options.commandLineArgv = debugger->Arguments();
options.settingsManager = debugger->GetSettingsManager();
status_t result = StartTeamDebugger(options);
if (result == B_OK)
debugger->PostMessage(B_QUIT_REQUESTED);
break;
}
default:
BLooper::MessageReceived(message);
break;
}
}


void
TargetHostInterface::TeamDebuggerStarted(TeamDebugger* debugger)
{
AutoLocker<TargetHostInterface> locker(this);
AddTeamDebugger(debugger);
}


void
TargetHostInterface::TeamDebuggerRestartRequested(TeamDebugger* debugger)
{
BMessage message(MSG_TEAM_RESTART_REQUESTED);
message.AddInt32("team", debugger->TeamID());
PostMessage(&message);
}


void
TargetHostInterface::TeamDebuggerQuit(TeamDebugger* debugger)
{
AutoLocker<TargetHostInterface> interfaceLocker(this);
RemoveTeamDebugger(debugger);
interfaceLocker.Unlock();

if (debugger->Thread() >= 0) {
BMessage message(MSG_TEAM_DEBUGGER_QUIT);
message.AddInt32("thread", debugger->Thread());
PostMessage(&message);
}
}


status_t
TargetHostInterface::_StartTeamDebugger(team_id teamID,
const TeamDebuggerOptions& options, bool stopInMain)
{
BReference<UserInterface> userInterfaceReference;
UserInterface* userInterface = options.userInterface;
if (userInterface == NULL) {
userInterface = new(std::nothrow) GraphicalUserInterface;
if (userInterface == NULL) {
fprintf(stderr, "Error: Out of memory!\n");
return B_NO_MEMORY;
}

userInterfaceReference.SetTo(userInterface, true);
}

thread_id threadID = options.thread;
if (options.commandLineArgv != NULL)
threadID = teamID;

DebuggerInterface* interface = NULL;
TeamDebugger* debugger = NULL;
status_t error = Attach(teamID, options.thread, interface);
if (error != B_OK) {
fprintf(stderr, "Error: Failed to attach to team %" B_PRId32 ": %s!\n",
teamID, strerror(error));
return error;
}

BReference<DebuggerInterface> debuggerInterfaceReference(interface,
true);
debugger = new(std::nothrow) TeamDebugger(this, userInterface,
options.settingsManager);
if (debugger != NULL) {
error = debugger->Init(interface, threadID,
options.commandLineArgc, options.commandLineArgv, stopInMain);
}

if (error != B_OK) {
printf("Error: debugger for team %" B_PRId32 " on interface %s failed"
" to init: %s!\n", interface->TeamID(), Name(), strerror(error));
delete debugger;
debugger = NULL;
} else {
printf("debugger for team %" B_PRId32 " on interface %s created and"
" initialized successfully!\n", interface->TeamID(), Name());
}

return error;
}


/*static*/ int
TargetHostInterface::_CompareDebuggers(const TeamDebugger* a,
const TeamDebugger* b)
Expand Down
47 changes: 38 additions & 9 deletions src/apps/debugger/target_host_interface/TargetHostInterface.h
Expand Up @@ -6,26 +6,28 @@
#define TARGET_HOST_INTERFACE_H

#include <OS.h>
#include <String.h>
#include <Looper.h>

#include <ObjectList.h>
#include <Referenceable.h>

#include "TeamDebugger.h"


class DebuggerInterface;
class Settings;
class SettingsManager;
class TargetHost;
class TeamDebugger;
struct TeamDebuggerOptions;
class UserInterface;


class TargetHostInterface : public BReferenceable {
class TargetHostInterface : public BLooper, private TeamDebugger::Listener {
public:
TargetHostInterface();
virtual ~TargetHostInterface();

const BString& Name() const { return fName; }
void SetName(const BString& name);

status_t StartTeamDebugger(const TeamDebuggerOptions& options);

int32 CountTeamDebuggers() const;
TeamDebugger* TeamDebuggerAt(int32 index) const;
Expand All @@ -36,18 +38,35 @@ class TargetHostInterface : public BReferenceable {
virtual status_t Init(Settings* settings) = 0;
virtual void Close() = 0;

virtual bool IsLocal() const = 0;
virtual bool Connected() const = 0;

virtual TargetHost* GetTargetHost() = 0;

virtual status_t Attach(team_id id, thread_id threadID,
DebuggerInterface*& _interface) = 0;
DebuggerInterface*& _interface) const = 0;

virtual status_t CreateTeam(int commandLineArgc,
const char* const* arguments,
DebuggerInterface*& _interface) = 0;
team_id& _teamID) const = 0;
virtual status_t FindTeamByThread(thread_id thread,
team_id& _teamID) const = 0;

// BLooper
virtual void Quit();
virtual void MessageReceived(BMessage* message);

private:
// TeamDebugger::Listener
virtual void TeamDebuggerStarted(TeamDebugger* debugger);
virtual void TeamDebuggerRestartRequested(
TeamDebugger* debugger);
virtual void TeamDebuggerQuit(TeamDebugger* debugger);

private:
status_t _StartTeamDebugger(team_id teamID,
const TeamDebuggerOptions& options,
bool stopInMain);
static int _CompareDebuggers(const TeamDebugger* a,
const TeamDebugger* b);
static int _FindDebuggerByKey(const team_id* team,
Expand All @@ -56,9 +75,19 @@ class TargetHostInterface : public BReferenceable {
typedef BObjectList<TeamDebugger> TeamDebuggerList;

private:
BString fName;
TeamDebuggerList fTeamDebuggers;
};


struct TeamDebuggerOptions {
TeamDebuggerOptions();
int commandLineArgc;
const char* const* commandLineArgv;
team_id team;
thread_id thread;
SettingsManager* settingsManager;
UserInterface* userInterface;
};


#endif // TARGET_HOST_INTERFACE_H
Expand Up @@ -130,12 +130,13 @@ TargetHostInterfaceRoster::CreateInterface(TargetHostInterfaceInfo* info,
if (error != B_OK)
return error;

BReference<TargetHostInterface> interfaceReference(interface, true);
if (!fActiveInterfaces.AddItem(interface))
error = interface->Run();
if (error < B_OK || !fActiveInterfaces.AddItem(interface)) {
delete interface;
return B_NO_MEMORY;
}

_interface = interface;
interfaceReference.Detach();
return B_OK;
}

Expand All @@ -153,3 +154,15 @@ TargetHostInterfaceRoster::ActiveInterfaceAt(int32 index) const
return fActiveInterfaces.ItemAt(index);
}


int32
TargetHostInterfaceRoster::CountRunningTeamDebuggers() const
{
int32 total = 0;
for (int32 i = 0; TargetHostInterface* interface = ActiveInterfaceAt(i);
i++) {
total += interface->CountTeamDebuggers();
}

return total;
}
Expand Up @@ -42,6 +42,8 @@ class TargetHostInterfaceRoster {
int32 CountActiveInterfaces() const;
TargetHostInterface* ActiveInterfaceAt(int32 index) const;

int32 CountRunningTeamDebuggers() const;

private:
typedef BObjectList<TargetHostInterfaceInfo> InfoList;
typedef BObjectList<TargetHostInterface> InterfaceList;
Expand Down

0 comments on commit a1afac4

Please sign in to comment.