diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index 72abdef437..e86bfb90f2 100644 --- a/src/apps/debugger/controllers/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -1369,6 +1370,17 @@ TeamDebugger::UserInterfaceQuitRequested(QuitOption quitOption) } +void +TeamDebugger::JobStarted(Job* job) +{ + BString description(job->GetDescription()); + if (!description.IsEmpty()) { + description.Append(B_UTF8_ELLIPSIS); + fUserInterface->NotifyBackgroundWorkStatus(description.String()); + } +} + + void TeamDebugger::JobDone(Job* job) { @@ -1377,6 +1389,21 @@ TeamDebugger::JobDone(Job* job) } +void +TeamDebugger::JobWaitingForInput(Job* job) +{ + LoadImageDebugInfoJob* infoJob = dynamic_cast(job); + + if (infoJob == NULL) + return; + + BMessage message(MSG_DEBUG_INFO_NEEDS_USER_INPUT); + message.AddPointer("job", infoJob); + message.AddPointer("state", infoJob->GetLoadingState()); + PostMessage(&message); +} + + void TeamDebugger::JobFailed(Job* job) { @@ -1396,30 +1423,6 @@ TeamDebugger::JobAborted(Job* job) } -void -TeamDebugger::ImageDebugInfoJobNeedsUserInput(Job* job, - ImageDebugInfoLoadingState* state) -{ - TRACE_JOBS("TeamDebugger::DebugInfoJobNeedsUserInput(%p, %p)\n", - job, state); - - BMessage message(MSG_DEBUG_INFO_NEEDS_USER_INPUT); - message.AddPointer("job", job); - message.AddPointer("state", state); - PostMessage(&message); -} - - -void -TeamDebugger::ImageDebugInfoJobInProgress(Image* image) -{ - BString message; - message.SetToFormat("Loading debug information for %s...", - image->Name().String()); - fUserInterface->NotifyBackgroundWorkStatus(message.String()); -} - - void TeamDebugger::ThreadStateChanged(const ::Team::ThreadEvent& event) { diff --git a/src/apps/debugger/controllers/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h index d588cf368d..7e645860bf 100644 --- a/src/apps/debugger/controllers/TeamDebugger.h +++ b/src/apps/debugger/controllers/TeamDebugger.h @@ -32,8 +32,7 @@ class WatchpointManager; class TeamDebugger : public BLooper, private UserInterfaceListener, - private JobListener, private ImageDebugInfoJobListener, - private Team::Listener { + private JobListener, private Team::Listener { public: class Listener; @@ -134,14 +133,12 @@ private: QuitOption quitOption); // JobListener + virtual void JobStarted(Job* job); virtual void JobDone(Job* job); + virtual void JobWaitingForInput(Job* job); virtual void JobFailed(Job* job); virtual void JobAborted(Job* job); - virtual void ImageDebugInfoJobNeedsUserInput(Job* job, - ImageDebugInfoLoadingState* state); - virtual void ImageDebugInfoJobInProgress(Image* image); - // Team::Listener virtual void ThreadStateChanged( const ::Team::ThreadEvent& event); diff --git a/src/apps/debugger/controllers/ThreadHandler.cpp b/src/apps/debugger/controllers/ThreadHandler.cpp index 999a6b0d12..fd5d228de5 100644 --- a/src/apps/debugger/controllers/ThreadHandler.cpp +++ b/src/apps/debugger/controllers/ThreadHandler.cpp @@ -76,14 +76,13 @@ private: ThreadHandler::ThreadHandler(Thread* thread, Worker* worker, - DebuggerInterface* debuggerInterface, - ImageDebugInfoJobListener* listener, + DebuggerInterface* debuggerInterface, JobListener* jobListener, BreakpointManager* breakpointManager) : fThread(thread), fWorker(worker), fDebuggerInterface(debuggerInterface), - fDebugInfoJobListener(listener), + fJobListener(jobListener), fBreakpointManager(breakpointManager), fStepMode(STEP_NONE), fStepStatement(NULL), @@ -113,7 +112,7 @@ void ThreadHandler::Init() { fWorker->ScheduleJob(new(std::nothrow) GetThreadStateJob(fDebuggerInterface, - fThread)); + fThread), fJobListener); fConditionWaitSem = create_sem(0, "breakpoint condition waiter"); } @@ -458,7 +457,8 @@ ThreadHandler::HandleThreadStateChanged() if (fThread->State() == THREAD_STATE_STOPPED && fThread->GetCpuState() == NULL) { fWorker->ScheduleJob( - new(std::nothrow) GetCpuStateJob(fDebuggerInterface, fThread)); + new(std::nothrow) GetCpuStateJob(fDebuggerInterface, fThread), + fJobListener); } } @@ -475,8 +475,8 @@ ThreadHandler::HandleCpuStateChanged() if (fThread->GetCpuState() != NULL && fThread->GetStackTrace() == NULL) { fWorker->ScheduleJob( new(std::nothrow) GetStackTraceJob(fDebuggerInterface, - fDebugInfoJobListener, fDebuggerInterface->GetArchitecture(), - fThread)); + fJobListener, fDebuggerInterface->GetArchitecture(), + fThread), fJobListener); } } @@ -954,7 +954,8 @@ ThreadHandler::_HandleBreakpointConditionIfNeeded(CpuState* cpuState) status_t error = fWorker->ScheduleJob( new(std::nothrow) ExpressionEvaluationJob(fThread->GetTeam(), - fDebuggerInterface, language, expressionInfo, frame, fThread)); + fDebuggerInterface, language, expressionInfo, frame, fThread), + fJobListener); BPrivate::ObjectDeleter deleter( listener); diff --git a/src/apps/debugger/controllers/ThreadHandler.h b/src/apps/debugger/controllers/ThreadHandler.h index 432eac1e9f..85ac8be6be 100644 --- a/src/apps/debugger/controllers/ThreadHandler.h +++ b/src/apps/debugger/controllers/ThreadHandler.h @@ -20,6 +20,7 @@ class BreakpointManager; class DebuggerInterface; class ExpressionResult; class ImageDebugInfoJobListener; +class JobListener; class StackFrame; class Statement; class Worker; @@ -30,7 +31,7 @@ class ThreadHandler : public BReferenceable, private ImageDebugInfoProvider, public: ThreadHandler(Thread* thread, Worker* worker, DebuggerInterface* debuggerInterface, - ImageDebugInfoJobListener* listener, + JobListener* listener, BreakpointManager* breakpointManager); ~ThreadHandler(); @@ -117,7 +118,7 @@ private: Thread* fThread; Worker* fWorker; DebuggerInterface* fDebuggerInterface; - ImageDebugInfoJobListener* fDebugInfoJobListener; + JobListener* fJobListener; BreakpointManager* fBreakpointManager; uint32 fStepMode; Statement* fStepStatement; diff --git a/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.cpp b/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.cpp index f174bfd11f..9cc89e0cc6 100644 --- a/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.cpp +++ b/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -108,6 +109,10 @@ DwarfLoadingStateHandler::HandleState( BString command; command.SetToFormat("/bin/pkgman install -y %s", requiredPackage.String()); + BString notification; + notification.SetToFormat("Installing package %s" B_UTF8_ELLIPSIS, + requiredPackage.String()); + interface->NotifyBackgroundWorkStatus(notification); int error = system(command.String()); if (interface->IsInteractive()) { if (WIFEXITED(error)) { diff --git a/src/apps/debugger/jobs/GetStackTraceJob.cpp b/src/apps/debugger/jobs/GetStackTraceJob.cpp index d0b28ce167..a44bbdbe36 100644 --- a/src/apps/debugger/jobs/GetStackTraceJob.cpp +++ b/src/apps/debugger/jobs/GetStackTraceJob.cpp @@ -18,12 +18,11 @@ GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface, - ImageDebugInfoJobListener* listener, Architecture* architecture, - Thread* thread) + JobListener* listener, Architecture* architecture, Thread* thread) : fKey(thread, JOB_TYPE_GET_STACK_TRACE), fDebuggerInterface(debuggerInterface), - fDebugInfoJobListener(listener), + fJobListener(listener), fArchitecture(architecture), fThread(thread) { @@ -32,6 +31,9 @@ GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface, fCpuState = fThread->GetCpuState(); if (fCpuState != NULL) fCpuState->AcquireReference(); + + + SetDescription("Retrieving stack trace for thread %" B_PRId32, fThread->ID()); } @@ -84,7 +86,7 @@ GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info) // schedule a job, if not loaded ImageDebugInfo* info; status_t error = LoadImageDebugInfoJob::ScheduleIfNecessary(GetWorker(), - image, fDebugInfoJobListener, &info); + image, fJobListener, &info); if (error != B_OK) return error; diff --git a/src/apps/debugger/jobs/Jobs.h b/src/apps/debugger/jobs/Jobs.h index 6e33346ace..e4b3e5bcab 100644 --- a/src/apps/debugger/jobs/Jobs.h +++ b/src/apps/debugger/jobs/Jobs.h @@ -92,20 +92,11 @@ private: }; -class ImageDebugInfoJobListener { -public: - virtual ~ImageDebugInfoJobListener(); - virtual void ImageDebugInfoJobNeedsUserInput(Job* job, - ImageDebugInfoLoadingState* state); - virtual void ImageDebugInfoJobInProgress(Image* image); -}; - - class GetStackTraceJob : public Job, private ImageDebugInfoProvider { public: GetStackTraceJob( DebuggerInterface* debuggerInterface, - ImageDebugInfoJobListener* listener, + JobListener* jobListener, Architecture* architecture, Thread* thread); virtual ~GetStackTraceJob(); @@ -120,7 +111,7 @@ private: private: SimpleJobKey fKey; DebuggerInterface* fDebuggerInterface; - ImageDebugInfoJobListener* fDebugInfoJobListener; + JobListener* fJobListener; Architecture* fArchitecture; Thread* fThread; CpuState* fCpuState; @@ -129,8 +120,7 @@ private: class LoadImageDebugInfoJob : public Job { public: - LoadImageDebugInfoJob(Image* image, - ImageDebugInfoJobListener* listener); + LoadImageDebugInfoJob(Image* image); virtual ~LoadImageDebugInfoJob(); virtual const JobKey& Key() const; @@ -138,7 +128,7 @@ public: static status_t ScheduleIfNecessary(Worker* worker, Image* image, - ImageDebugInfoJobListener* listener, + JobListener* jobListener, ImageDebugInfo** _imageDebugInfo = NULL); // If already loaded returns a // reference, if desired. If not loaded @@ -147,19 +137,16 @@ public: // if scheduling the job failed, or the // debug info already failed to load // earlier. -private: - void NotifyUserInputListener(); - -private: - typedef BObjectList ListenerList; + ImageDebugInfoLoadingState* + GetLoadingState() + { return &fState; } private: SimpleJobKey fKey; Image* fImage; ImageDebugInfoLoadingState fState; - ImageDebugInfoJobListener* fListener; }; diff --git a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp index 06a88b70a8..d576f08fb2 100644 --- a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp +++ b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp @@ -14,39 +14,19 @@ #include "Team.h" -// #pragma mark - ImageDebugInfoJobListener - - -ImageDebugInfoJobListener::~ImageDebugInfoJobListener() -{ -} - - -void -ImageDebugInfoJobListener::ImageDebugInfoJobNeedsUserInput(Job* job, - ImageDebugInfoLoadingState* state) -{ -} - - -void -ImageDebugInfoJobListener::ImageDebugInfoJobInProgress(Image* image) -{ -} - - // #pragma mark - LoadImageDebugInfoJob -LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image, - ImageDebugInfoJobListener* listener) +LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image) : fKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO), fImage(image), - fState(), - fListener(listener) + fState() { fImage->AcquireReference(); + + SetDescription("Loading debugging information for %s", + fImage->Name().String()); } @@ -71,9 +51,6 @@ LoadImageDebugInfoJob::Do() ImageInfo imageInfo(fImage->Info()); locker.Unlock(); - if (fListener != NULL) - fListener->ImageDebugInfoJobInProgress(fImage); - // create the debug info ImageDebugInfo* debugInfo; status_t error = fImage->GetTeam()->DebugInfo()->LoadImageDebugInfo( @@ -83,7 +60,6 @@ LoadImageDebugInfoJob::Do() locker.Lock(); if (fState.UserInputRequired()) { - NotifyUserInputListener(); return WaitForUserInput(); } else if (error == B_OK) { error = fImage->SetImageDebugInfo(debugInfo, IMAGE_DEBUG_INFO_LOADED); @@ -97,7 +73,7 @@ LoadImageDebugInfoJob::Do() /*static*/ status_t LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image, - ImageDebugInfoJobListener* listener, ImageDebugInfo** _imageDebugInfo) + JobListener* listener, ImageDebugInfo** _imageDebugInfo) { AutoLocker teamLocker(image->GetTeam()); @@ -122,12 +98,12 @@ LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image, return B_ERROR; // schedule a job - LoadImageDebugInfoJob* job = new(std::nothrow) LoadImageDebugInfoJob(image, - listener); + LoadImageDebugInfoJob* job = new(std::nothrow) LoadImageDebugInfoJob( + image); if (job == NULL) return B_NO_MEMORY; - status_t error = worker->ScheduleJob(job); + status_t error = worker->ScheduleJob(job, listener); if (error != B_OK) { image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE); return error; @@ -139,12 +115,3 @@ LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image, *_imageDebugInfo = NULL; return B_OK; } - - -void -LoadImageDebugInfoJob::NotifyUserInputListener() -{ - if (fListener != NULL) - fListener->ImageDebugInfoJobNeedsUserInput(this, &fState); -} - diff --git a/src/apps/debugger/jobs/LoadSourceCodeJob.cpp b/src/apps/debugger/jobs/LoadSourceCodeJob.cpp index 402a9ab711..6265a03ff3 100644 --- a/src/apps/debugger/jobs/LoadSourceCodeJob.cpp +++ b/src/apps/debugger/jobs/LoadSourceCodeJob.cpp @@ -30,6 +30,9 @@ LoadSourceCodeJob::LoadSourceCodeJob( fLoadForFunction(loadForFunction) { fFunctionInstance->AcquireReference(); + + SetDescription("Loading source code for function %s", + fFunctionInstance->PrettyName().String()); } diff --git a/src/apps/debugger/util/Worker.cpp b/src/apps/debugger/util/Worker.cpp index f1f58ab380..0a184bdfbc 100644 --- a/src/apps/debugger/util/Worker.cpp +++ b/src/apps/debugger/util/Worker.cpp @@ -70,12 +70,24 @@ JobListener::~JobListener() } +void +JobListener::JobStarted(Job* job) +{ +} + + void JobListener::JobDone(Job* job) { } +void +JobListener::JobWaitingForInput(Job* job) +{ +} + + void JobListener::JobFailed(Job* job) { @@ -121,6 +133,15 @@ Job::WaitForUserInput() } +void +Job::SetDescription(const char* format, ...) +{ + va_list args; + va_start(args, format); + fDescription.SetToFormatVarArgs(format, args); +} + + void Job::SetWorker(Worker* worker) { @@ -179,6 +200,13 @@ Job::NotifyListeners() for (int32 i = count - 1; i >= 0; i--) { JobListener* listener = fListeners.ItemAt(i); switch (fState) { + case JOB_STATE_ACTIVE: + listener->JobStarted(this); + break; + case JOB_STATE_WAITING: + if (fWaitStatus == JOB_USER_INPUT_WAITING) + listener->JobWaitingForInput(this); + break; case JOB_STATE_SUCCEEDED: listener->JobDone(this); break; @@ -403,6 +431,7 @@ Worker::WaitForUserInput(Job* waitingJob) return B_INTERRUPTED; waitingJob->SetWaitStatus(JOB_USER_INPUT_WAITING); + waitingJob->NotifyListeners(); fSuspendedJobs.Add(waitingJob); return B_OK; @@ -459,6 +488,7 @@ Worker::_ProcessJobs() // process the next job if (Job* job = fUnscheduledJobs.RemoveHead()) { job->SetState(JOB_STATE_ACTIVE); + job->NotifyListeners(); locker.Unlock(); status_t error = job->Do(); diff --git a/src/apps/debugger/util/Worker.h b/src/apps/debugger/util/Worker.h index c993f4dee0..d27abe7a07 100644 --- a/src/apps/debugger/util/Worker.h +++ b/src/apps/debugger/util/Worker.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -69,7 +70,9 @@ class JobListener { public: virtual ~JobListener(); + virtual void JobStarted(Job* job); virtual void JobDone(Job* job); + virtual void JobWaitingForInput(Job* job); virtual void JobFailed(Job* job); virtual void JobAborted(Job* job); }; @@ -89,9 +92,13 @@ public: Worker* GetWorker() const { return fWorker; } job_state State() const { return fState; } + const BString& GetDescription() const + { return fDescription; } + protected: job_wait_status WaitFor(const JobKey& key); status_t WaitForUserInput(); + void SetDescription(const char* format, ...); private: friend class Worker; @@ -122,6 +129,7 @@ private: JobList fDependentJobs; job_wait_status fWaitStatus; ListenerList fListeners; + BString fDescription; public: Job* fNext;