From 6e97df31a0a18dc0ca522a0b8b4aae250e102760 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sat, 28 Nov 2015 23:53:11 -0500 Subject: [PATCH] Debugger: Add team event handling to expression window. ExpressionEvaluationWindow: - Add team listener hooks for the various thread state changes. - Implement these to react accordingly and keep the thread/frame menus up to date with running program changes, whether due to user interaction in the main team window, or background activities of the debugged app. Previously the evaluation window needed to be closed and reopened to refresh these appropriately. --- .../ExpressionEvaluationWindow.cpp | 214 ++++++++++++++++-- .../ExpressionEvaluationWindow.h | 19 +- 2 files changed, 216 insertions(+), 17 deletions(-) diff --git a/src/apps/debugger/user_interface/gui/expression_eval_window/ExpressionEvaluationWindow.cpp b/src/apps/debugger/user_interface/gui/expression_eval_window/ExpressionEvaluationWindow.cpp index b1877c447e..e182a34a0f 100644 --- a/src/apps/debugger/user_interface/gui/expression_eval_window/ExpressionEvaluationWindow.cpp +++ b/src/apps/debugger/user_interface/gui/expression_eval_window/ExpressionEvaluationWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2014-2015, Rene Gollent, rene@gollent.com. + * Copyright 2014-2016, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #include "ExpressionEvaluationWindow.h" @@ -10,7 +10,9 @@ #include #include -#include "AutoLocker.h" +#include +#include + #include "CppLanguage.h" #include "FunctionDebugInfo.h" #include "FunctionInstance.h" @@ -26,6 +28,9 @@ enum { + MSG_THREAD_ADDED = 'thad', + MSG_THREAD_REMOVED = 'thar', + MSG_THREAD_SELECTION_CHANGED = 'thsc', MSG_FRAME_SELECTION_CHANGED = 'frsc' }; @@ -144,6 +149,38 @@ ExpressionEvaluationWindow::MessageReceived(BMessage* message) break; } + case MSG_THREAD_ADDED: + { + int32 threadID; + if (message->FindInt32("thread", &threadID) == B_OK) + _HandleThreadAdded(threadID); + break; + } + + case MSG_THREAD_REMOVED: + { + int32 threadID; + if (message->FindInt32("thread", &threadID) == B_OK) + _HandleThreadRemoved(threadID); + break; + } + + case MSG_THREAD_STATE_CHANGED: + { + int32 threadID; + if (message->FindInt32("thread", &threadID) == B_OK) + _HandleThreadStateChanged(threadID); + break; + } + + case MSG_THREAD_STACK_TRACE_CHANGED: + { + int32 threadID; + if (message->FindInt32("thread", &threadID) == B_OK) + _HandleThreadStackTraceChanged(threadID); + break; + } + default: BWindow::MessageReceived(message); break; @@ -152,6 +189,43 @@ ExpressionEvaluationWindow::MessageReceived(BMessage* message) } +void +ExpressionEvaluationWindow::ThreadAdded(const Team::ThreadEvent& event) +{ + BMessage message(MSG_THREAD_ADDED); + message.AddInt32("thread", event.GetThread()->ID()); + PostMessage(&message); +} + + +void +ExpressionEvaluationWindow::ThreadRemoved(const Team::ThreadEvent& event) +{ + BMessage message(MSG_THREAD_REMOVED); + message.AddInt32("thread", event.GetThread()->ID()); + PostMessage(&message); +} + + +void +ExpressionEvaluationWindow::ThreadStateChanged(const Team::ThreadEvent& event) +{ + BMessage message(MSG_THREAD_STATE_CHANGED); + message.AddInt32("thread", event.GetThread()->ID()); + PostMessage(&message); +} + + +void +ExpressionEvaluationWindow::ThreadStackTraceChanged( + const Team::ThreadEvent& event) +{ + BMessage message(MSG_THREAD_STACK_TRACE_CHANGED); + message.AddInt32("thread", event.GetThread()->ID()); + PostMessage(&message); +} + + void ExpressionEvaluationWindow::ValueNodeValueRequested(CpuState* cpuState, ValueNodeContainer* container, ValueNode* valueNode) @@ -240,6 +314,12 @@ ExpressionEvaluationWindow::_HandleThreadSelectionChanged(int32 threadID) fSelectedThread = fTeam->ThreadByID(threadID); if (fSelectedThread != NULL) fSelectedThread->AcquireReference(); + else if (fThreadList->Menu()->FindMarked() == NULL) { + // if the selected thread was cleared due to a thread event + // rather than user selection, we need to reset the marked item + // to reflect the new state. + fThreadList->Menu()->ItemAt(0)->SetMarked(true); + } _UpdateFrameList(); @@ -286,6 +366,93 @@ ExpressionEvaluationWindow::_HandleFrameSelectionChanged(int32 index) } +void +ExpressionEvaluationWindow::_HandleThreadAdded(int32 threadID) +{ + AutoLocker< ::Team> teamLocker(fTeam); + ::Thread* thread = fTeam->ThreadByID(threadID); + if (thread == NULL) + return; + + if (thread->State() != THREAD_STATE_STOPPED) + return; + + BMenuItem* item = NULL; + if (_CreateThreadMenuItem(thread, item) != B_OK) + return; + + BMenu* threadMenu = fThreadList->Menu(); + int32 index = 1; + // find appropriate insertion index to keep menu sorted in thread order. + for (; index < threadMenu->CountItems(); index++) { + BMenuItem* threadItem = threadMenu->ItemAt(index); + BMessage* message = threadItem->Message(); + if (message->FindInt32("thread") > threadID) + break; + } + + bool added = false; + if (index == threadMenu->CountItems()) + added = threadMenu->AddItem(item); + else + added = threadMenu->AddItem(item, index); + + if (!added) + delete item; +} + + +void +ExpressionEvaluationWindow::_HandleThreadRemoved(int32 threadID) +{ + BMenu* threadMenu = fThreadList->Menu(); + for (int32 i = 0; i < threadMenu->CountItems(); i++) { + BMenuItem* item = threadMenu->ItemAt(i); + BMessage* message = item->Message(); + if (message->FindInt32("thread") == threadID) { + threadMenu->RemoveItem(i); + delete item; + break; + } + } + + if (fSelectedThread != NULL && threadID == fSelectedThread->ID()) + _HandleThreadSelectionChanged(-1); +} + + +void +ExpressionEvaluationWindow::_HandleThreadStateChanged(int32 threadID) +{ + AutoLocker< ::Team> teamLocker(fTeam); + + ::Thread* thread = fTeam->ThreadByID(threadID); + if (thread == NULL) + return; + + if (thread->State() == THREAD_STATE_STOPPED) + _HandleThreadAdded(threadID); + else + _HandleThreadRemoved(threadID); +} + + +void +ExpressionEvaluationWindow::_HandleThreadStackTraceChanged(int32 threadID) +{ + AutoLocker< ::Team> teamLocker(fTeam); + + ::Thread* thread = fTeam->ThreadByID(threadID); + if (thread == NULL) + return; + + if (thread != fSelectedThread) + return; + + _UpdateFrameList(); +} + + void ExpressionEvaluationWindow::_UpdateThreadList() { @@ -305,25 +472,15 @@ ExpressionEvaluationWindow::_UpdateThreadList() if (thread->State() != THREAD_STATE_STOPPED) continue; - BString nameString; - nameString.SetToFormat("%" B_PRId32 ": %s", thread->ID(), - thread->Name()); - - BMessage* message = new(std::nothrow) BMessage( - MSG_THREAD_SELECTION_CHANGED); - if (message == NULL) - return; - - message->AddInt32("thread", thread->ID()); - - BMenuItem* item = new(std::nothrow) BMenuItem(nameString, - message); - if (item == NULL) + BMenuItem* item = NULL; + if (_CreateThreadMenuItem(thread, item) != B_OK) return; + ObjectDeleter itemDeleter(item); if (!threadMenu->AddItem(item)) return; + itemDeleter.Detach(); if (fSelectedThread == NULL) { item->SetMarked(true); _HandleThreadSelectionChanged(thread->ID()); @@ -380,3 +537,28 @@ ExpressionEvaluationWindow::_UpdateFrameList() } } } + + +status_t +ExpressionEvaluationWindow::_CreateThreadMenuItem(::Thread* thread, + BMenuItem*& _item) const +{ + BString nameString; + nameString.SetToFormat("%" B_PRId32 ": %s", thread->ID(), + thread->Name()); + + BMessage* message = new(std::nothrow) BMessage( + MSG_THREAD_SELECTION_CHANGED); + if (message == NULL) + return B_NO_MEMORY; + + ObjectDeleter messageDeleter(message); + message->AddInt32("thread", thread->ID()); + _item = new(std::nothrow) BMenuItem(nameString, + message); + if (_item == NULL) + return B_NO_MEMORY; + + messageDeleter.Detach(); + return B_OK; +} diff --git a/src/apps/debugger/user_interface/gui/expression_eval_window/ExpressionEvaluationWindow.h b/src/apps/debugger/user_interface/gui/expression_eval_window/ExpressionEvaluationWindow.h index f104f212b8..c95ea6b379 100644 --- a/src/apps/debugger/user_interface/gui/expression_eval_window/ExpressionEvaluationWindow.h +++ b/src/apps/debugger/user_interface/gui/expression_eval_window/ExpressionEvaluationWindow.h @@ -1,5 +1,5 @@ /* - * Copyright 2014-2015, Rene Gollent, rene@gollent.com. + * Copyright 2014-2016, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef EXPRESSION_EVALUATION_WINDOW_H @@ -41,6 +41,15 @@ public: virtual void MessageReceived(BMessage* message); + // Team::Listener + virtual void ThreadAdded(const Team::ThreadEvent& event); + virtual void ThreadRemoved(const Team::ThreadEvent& event); + + virtual void ThreadStateChanged( + const Team::ThreadEvent& event); + virtual void ThreadStackTraceChanged( + const Team::ThreadEvent& event); + // VariablesView::Listener virtual void ValueNodeValueRequested(CpuState* cpuState, ValueNodeContainer* container, @@ -62,9 +71,17 @@ private: void _HandleThreadSelectionChanged(int32 threadID); void _HandleFrameSelectionChanged(int32 index); + void _HandleThreadAdded(int32 threadID); + void _HandleThreadRemoved(int32 threadID); + void _HandleThreadStateChanged(int32 threadID); + void _HandleThreadStackTraceChanged(int32 threadID); + void _UpdateThreadList(); void _UpdateFrameList(); + status_t _CreateThreadMenuItem(::Thread* thread, + BMenuItem*& _item) const; + private: BTextControl* fExpressionInput; BMenuField* fThreadList;