Refactor DebugReportGenerator to use jobs.

- Instead of asking nodes to resolve themselves directly,
  DebugReportGenerator now uses the interface listener to ask the
  debugger's workers to resolve them on its behalf.
This commit is contained in:
Rene Gollent
2012-12-11 22:56:47 -05:00
parent 00e7e607ef
commit be56273bbb
3 changed files with 67 additions and 26 deletions
@@ -28,6 +28,7 @@
#include "Thread.h" #include "Thread.h"
#include "Type.h" #include "Type.h"
#include "UiUtils.h" #include "UiUtils.h"
#include "UserInterface.h"
#include "Value.h" #include "Value.h"
#include "ValueLoader.h" #include "ValueLoader.h"
#include "ValueLocation.h" #include "ValueLocation.h"
@@ -35,13 +36,17 @@
#include "ValueNodeManager.h" #include "ValueNodeManager.h"
DebugReportGenerator::DebugReportGenerator(::Team* team) DebugReportGenerator::DebugReportGenerator(::Team* team,
UserInterfaceListener* listener)
: :
BLooper("DebugReportGenerator"), BLooper("DebugReportGenerator"),
fTeam(team), fTeam(team),
fArchitecture(team->GetArchitecture()), fArchitecture(team->GetArchitecture()),
fTeamDataSem(-1), fTeamDataSem(-1),
fNodeManager(NULL) fNodeManager(NULL),
fListener(listener),
fWaitingNode(NULL),
fTraceWaitingThread(NULL)
{ {
fTeam->AddListener(this); fTeam->AddListener(this);
fArchitecture->AcquireReference(); fArchitecture->AcquireReference();
@@ -52,8 +57,10 @@ DebugReportGenerator::~DebugReportGenerator()
{ {
fTeam->RemoveListener(this); fTeam->RemoveListener(this);
fArchitecture->ReleaseReference(); fArchitecture->ReleaseReference();
if (fNodeManager != NULL) if (fNodeManager != NULL) {
fNodeManager->RemoveListener(this);
fNodeManager->ReleaseReference(); fNodeManager->ReleaseReference();
}
} }
@@ -68,6 +75,8 @@ DebugReportGenerator::Init()
if (fNodeManager == NULL) if (fNodeManager == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
fNodeManager->AddListener(this);
Run(); Run();
return B_OK; return B_OK;
@@ -75,9 +84,9 @@ DebugReportGenerator::Init()
DebugReportGenerator* DebugReportGenerator*
DebugReportGenerator::Create(::Team* team) DebugReportGenerator::Create(::Team* team, UserInterfaceListener* listener)
{ {
DebugReportGenerator* self = new DebugReportGenerator(team); DebugReportGenerator* self = new DebugReportGenerator(team, listener);
try { try {
self->Init(); self->Init();
@@ -145,7 +154,20 @@ DebugReportGenerator::MessageReceived(BMessage* message)
void void
DebugReportGenerator::ThreadStackTraceChanged(const ::Team::ThreadEvent& event) DebugReportGenerator::ThreadStackTraceChanged(const ::Team::ThreadEvent& event)
{ {
release_sem(fTeamDataSem); if (fTraceWaitingThread == event.GetThread()) {
fTraceWaitingThread = NULL;
release_sem(fTeamDataSem);
}
}
void
DebugReportGenerator::ValueNodeValueChanged(ValueNode* node)
{
if (node == fWaitingNode) {
fWaitingNode = NULL;
release_sem(fTeamDataSem);
}
} }
@@ -280,6 +302,7 @@ DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output,
break; break;
locker.Unlock(); locker.Unlock();
fTraceWaitingThread = thread;
status_t result = acquire_sem(fTeamDataSem); status_t result = acquire_sem(fTeamDataSem);
if (result != B_OK) if (result != B_OK)
return result; return result;
@@ -312,9 +335,10 @@ DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output,
AutoLocker<ValueNodeContainer> containerLocker(container); AutoLocker<ValueNodeContainer> containerLocker(container);
for (int32 i = 0; i < container->CountChildren(); i++) { for (int32 i = 0; i < container->CountChildren(); i++) {
ValueNodeChild* child = container->ChildAt(i); ValueNodeChild* child = container->ChildAt(i);
_ResolveLocationIfNeeded(child, frame); containerLocker.Unlock();
_ResolveValueIfNeeded(child->Node(), frame, 4); _ResolveValueIfNeeded(child->Node(), frame, 1);
UiUtils::PrintValueNodeGraph(_output, frame, child, 3, 2); containerLocker.Lock();
UiUtils::PrintValueNodeGraph(_output, frame, child, 3, 1);
} }
_output << "\n"; _output << "\n";
} }
@@ -342,21 +366,20 @@ status_t
DebugReportGenerator::_ResolveValueIfNeeded(ValueNode* node, StackFrame* frame, DebugReportGenerator::_ResolveValueIfNeeded(ValueNode* node, StackFrame* frame,
int32 maxDepth) int32 maxDepth)
{ {
ValueLocation* location = NULL; status_t result = B_OK;
Value* value = NULL; if (node->LocationAndValueResolutionState() == VALUE_NODE_UNRESOLVED) {
ValueLoader loader(fTeam->GetArchitecture(), fTeam->GetTeamMemory(), fWaitingNode = node;
fTeam->GetTeamTypeInformation(), frame->GetCpuState()); fListener->ValueNodeValueRequested(frame->GetCpuState(),
status_t result = node->ResolvedLocationAndValue(&loader, location, fNodeManager->GetContainer(), node);
value); result = acquire_sem(fTeamDataSem);
node->SetLocationAndValue(location, value, result); }
if (location != NULL)
location->ReleaseReference();
if (value != NULL)
value->ReleaseReference();
if (result == B_OK && maxDepth > 0) { if (node->LocationAndValueResolutionState() == B_OK && maxDepth > 0) {
AutoLocker<ValueNodeContainer> containerLocker(
fNodeManager->GetContainer());
for (int32 i = 0; i < node->CountChildren(); i++) { for (int32 i = 0; i < node->CountChildren(); i++) {
ValueNodeChild* child = node->ChildAt(i); ValueNodeChild* child = node->ChildAt(i);
containerLocker.Unlock();
result = _ResolveLocationIfNeeded(child, frame); result = _ResolveLocationIfNeeded(child, frame);
if (result != B_OK) if (result != B_OK)
continue; continue;
@@ -365,7 +388,15 @@ DebugReportGenerator::_ResolveValueIfNeeded(ValueNode* node, StackFrame* frame,
if (result != B_OK) if (result != B_OK)
continue; continue;
_ResolveValueIfNeeded(child->Node(), frame, maxDepth - 1); // since in the case of a pointer to a compound we hide
// the intervening compound, don't consider the hidden node
// a level for the purposes of depth traversal
if (node->GetType()->Kind() == TYPE_ADDRESS
&& child->GetType()->Kind() == TYPE_COMPOUND) {
_ResolveValueIfNeeded(child->Node(), frame, maxDepth);
} else
_ResolveValueIfNeeded(child->Node(), frame, maxDepth - 1);
containerLocker.Lock();
} }
} }
@@ -9,6 +9,7 @@
#include <Looper.h> #include <Looper.h>
#include "Team.h" #include "Team.h"
#include "ValueNodeContainer.h"
class entry_ref; class entry_ref;
@@ -17,26 +18,32 @@ class BString;
class StackFrame; class StackFrame;
class Team; class Team;
class Thread; class Thread;
class UserInterfaceListener;
class Value; class Value;
class ValueNode; class ValueNode;
class ValueNodeChild; class ValueNodeChild;
class ValueNodeManager; class ValueNodeManager;
class DebugReportGenerator : public BLooper, public Team::Listener { class DebugReportGenerator : public BLooper, private Team::Listener,
private ValueNodeContainer::Listener {
public: public:
DebugReportGenerator(::Team* team); DebugReportGenerator(::Team* team,
UserInterfaceListener* listener);
~DebugReportGenerator(); ~DebugReportGenerator();
status_t Init(); status_t Init();
static DebugReportGenerator* Create(::Team* team); static DebugReportGenerator* Create(::Team* team,
UserInterfaceListener* listener);
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
virtual void ThreadStackTraceChanged( virtual void ThreadStackTraceChanged(
const Team::ThreadEvent& event); const Team::ThreadEvent& event);
virtual void ValueNodeValueChanged(ValueNode* node);
private: private:
status_t _GenerateReport(const entry_ref& outputPath); status_t _GenerateReport(const entry_ref& outputPath);
status_t _GenerateReportHeader(BString& output); status_t _GenerateReportHeader(BString& output);
@@ -55,6 +62,9 @@ private:
Architecture* fArchitecture; Architecture* fArchitecture;
sem_id fTeamDataSem; sem_id fTeamDataSem;
ValueNodeManager* fNodeManager; ValueNodeManager* fNodeManager;
UserInterfaceListener* fListener;
ValueNode* fWaitingNode;
::Thread* fTraceWaitingThread;
}; };
#endif // DEBUG_REPORT_GENERATOR_H #endif // DEBUG_REPORT_GENERATOR_H
@@ -416,7 +416,7 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain)
return error; return error;
// create the debug report generator // create the debug report generator
fReportGenerator = new(std::nothrow) DebugReportGenerator(fTeam); fReportGenerator = new(std::nothrow) DebugReportGenerator(fTeam, this);
if (fReportGenerator == NULL) if (fReportGenerator == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;