Skip to content

Commit

Permalink
medic: fix flicker in threads and stack trace while stepping
Browse files Browse the repository at this point in the history
  • Loading branch information
jafl committed May 29, 2024
1 parent 5720e99 commit 93ac973
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 16 deletions.
9 changes: 4 additions & 5 deletions code_medic/backend/lldb/GetThreadsCmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ lldb::GetThreadsCmd::~GetThreadsCmd()
******************************************************************************/

static const JRegex threadIDPattern("^thread #([[:digit:]]+):\\s*tid = [^,]+,");
static const JRegex threadIDPattern("^thread #([[:digit:]]+):\\s*tid\\s*=\\s*([^,]+),");

void
lldb::GetThreadsCmd::HandleSuccess
Expand Down Expand Up @@ -110,14 +110,13 @@ lldb::GetThreadsCmd::HandleSuccess
const JStringMatch m = threadIDPattern.Match(name, JRegex::kIncludeSubmatches);
if (!m.IsEmpty())
{
indexStr = m.GetSubstring(1);

JUInt indexValue;
if (indexStr.ConvertToUInt(&indexValue) && indexValue == threadID)
JUInt idValue;
if (m.GetSubstring(2).ConvertToUInt(&idValue) && idValue == threadID)
{
foundThreadID = true;
}

indexStr = m.GetSubstring(1);
while (indexStr.GetCharacterCount() < kThreadIndexWidth)
{
indexStr.Prepend("0");
Expand Down
23 changes: 21 additions & 2 deletions code_medic/code/Link.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include <jx-af/jcore/jFileUtil.h>
#include <jx-af/jcore/jAssert.h>

const JSize kPauseForStepInterval = 2000; // ms

// JBroadcaster message types

const JUtf8Byte* Link::kUserOutput = "UserOutput::Link";
Expand Down Expand Up @@ -60,13 +62,15 @@ Link::Link
const bool* features,
const JUtf8Byte* cmdPromptKey,
const JUtf8Byte* scriptPromptKey,
const JUtf8Byte* chooseProgInstrKey
const JUtf8Byte* chooseProgInstrKey,
const Time pauseForStepInterval
)
:
itsFeatures(features),
itsCommandPromptKey(cmdPromptKey),
itsScriptPromptKey(scriptPromptKey),
itsChooseProgramInstructionsKey(chooseProgInstrKey)
itsChooseProgramInstructionsKey(chooseProgInstrKey),
itsPauseForStepInterval(pauseForStepInterval > 0 ? pauseForStepInterval : kPauseForStepInterval)
{
// commands are often owned by other objects, who can delete them more reliably
itsForegroundQ = jnew JPtrArray<Command>(JPtrArrayT::kForgetAll);
Expand Down Expand Up @@ -129,6 +133,21 @@ Link::GetChooseProgramInstructions()
return JGetString(itsChooseProgramInstructionsKey);
}

/******************************************************************************
GetPauseForStepInterval
How long to wait before assuming that the program is running rather than
stepping.
******************************************************************************/

JSize
Link::GetPauseForStepInterval()
const
{
return itsPauseForStepInterval;
}

/******************************************************************************
DeleteOneShotCommands (private)
Expand Down
6 changes: 5 additions & 1 deletion code_medic/code/Link.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ class Link : virtual public JBroadcaster
public:

Link(const bool* features, const JUtf8Byte* cmdPromptKey,
const JUtf8Byte* scriptPromptKey, const JUtf8Byte* chooseProgInstrKey);
const JUtf8Byte* scriptPromptKey, const JUtf8Byte* chooseProgInstrKey,
const JSize pauseForStepInterval = 0);

~Link() override;

Expand Down Expand Up @@ -172,6 +173,8 @@ class Link : virtual public JBroadcaster
bool* exists, JString* fullName) const;
void ClearFileNameMap();

JSize GetPauseForStepInterval() const;

static void NotifyUser(const JString& msg, const bool error);
static void Log(const JUtf8Byte* log);
static void Log(std::ostringstream& log);
Expand Down Expand Up @@ -245,6 +248,7 @@ class Link : virtual public JBroadcaster
const JUtf8Byte* itsCommandPromptKey;
const JUtf8Byte* itsScriptPromptKey;
const JUtf8Byte* itsChooseProgramInstructionsKey;
const JSize itsPauseForStepInterval;

Command* itsRunningCommand;
JIndex itsLastCommandID;
Expand Down
23 changes: 20 additions & 3 deletions code_medic/code/StackWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "GetFrameCmd.h"
#include "globals.h"
#include <jx-af/jx/JXWindow.h>
#include <jx-af/jx/JXFunctionTask.h>
#include <jx-af/jcore/JTree.h>
#include <jx-af/jcore/JNamedTreeList.h>
#include <jx-af/jcore/JTableSelection.h>
Expand Down Expand Up @@ -57,7 +58,8 @@ StackWidget::StackWidget
itsSmartFrameSelectFlag(false),
itsIsWaitingForReloadFlag(false),
itsChangingFrameFlag(false),
itsSelectingFrameFlag(false)
itsSelectingFrameFlag(false),
itsFlushStateTask(nullptr)
{
itsLink = GetLink();
ListenTo(itsLink);
Expand Down Expand Up @@ -90,6 +92,7 @@ StackWidget::~StackWidget()
jdelete itsTree;
jdelete itsGetStackCmd;
jdelete itsGetFrameCmd;
jdelete itsFlushStateTask;
}

/******************************************************************************
Expand Down Expand Up @@ -430,9 +433,20 @@ StackWidget::Receive
Rebuild();
}

else if (sender == itsLink && message.Is(Link::kProgramRunning))
{
itsIsWaitingForReloadFlag = false;
itsFlushStateTask = jnew JXFunctionTask(itsLink->GetPauseForStepInterval(), [this]()
{
itsFlushStateTask = nullptr;
FlushOldData();
},
"StackWidget::PauseBeforeFlushOldData",
true);
itsFlushStateTask->Start();
}
else if (sender == itsLink &&
(message.Is(Link::kProgramRunning) ||
message.Is(Link::kProgramFinished) ||
(message.Is(Link::kProgramFinished) ||
message.Is(Link::kDetachedFromProcess)))
{
itsIsWaitingForReloadFlag = false;
Expand All @@ -451,6 +465,9 @@ StackWidget::Receive
}
else if (sender == itsLink && message.Is(Link::kProgramStopped))
{
jdelete itsFlushStateTask;
itsFlushStateTask = nullptr;

auto& info = dynamic_cast<const Link::ProgramStopped&>(message);
if (!info.IsWaitingForThread())
{
Expand Down
2 changes: 2 additions & 0 deletions code_medic/code/StackWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <jx-af/jx/JXNamedTreeListWidget.h>

class JTree;
class JXIdleTask;
class Link;
class CommandDirector;
class StackDir;
Expand Down Expand Up @@ -73,6 +74,7 @@ class StackWidget : public JXNamedTreeListWidget
bool itsIsWaitingForReloadFlag;
bool itsChangingFrameFlag;
bool itsSelectingFrameFlag;
JXIdleTask* itsFlushStateTask;

private:

Expand Down
26 changes: 22 additions & 4 deletions code_medic/code/ThreadsWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "GetThreadCmd.h"
#include "globals.h"
#include <jx-af/jx/JXWindow.h>
#include <jx-af/jx/JXFunctionTask.h>
#include <jx-af/jx/JXDeleteObjectTask.h>
#include <jx-af/jcore/JTree.h>
#include <jx-af/jcore/JNamedTreeList.h>
Expand All @@ -33,7 +34,7 @@
ThreadsWidget::ThreadsWidget
(
CommandDirector* commandDir,
ThreadsDir* threadDir,
ThreadsDir* threadDir,
JTree* tree,
JNamedTreeList* treeList,
JXScrollbarSet* scrollbarSet,
Expand All @@ -57,7 +58,8 @@ ThreadsWidget::ThreadsWidget
itsChangingThreadFlag(false),
itsSelectingThreadFlag(false),
itsFlushWhenRunFlag(true),
itsOpenIDList(nullptr)
itsOpenIDList(nullptr),
itsFlushStateTask(nullptr)
{
itsLink = GetLink();
ListenTo(itsLink);
Expand Down Expand Up @@ -87,6 +89,7 @@ ThreadsWidget::~ThreadsWidget()
JXDeleteObjectTask<GetThreadsCmd>::Delete(itsGetThreadsCmd);
jdelete itsGetCurrentThreadCmd;
jdelete itsOpenIDList;
jdelete itsFlushStateTask;
}

/******************************************************************************
Expand Down Expand Up @@ -350,8 +353,20 @@ ThreadsWidget::Receive
}

else if (sender == itsLink &&
((message.Is(Link::kProgramRunning) && itsFlushWhenRunFlag) ||
message.Is(Link::kProgramFinished) ||
(message.Is(Link::kProgramRunning) && itsFlushWhenRunFlag))
{
itsIsWaitingForReloadFlag = false;
itsFlushStateTask = jnew JXFunctionTask(itsLink->GetPauseForStepInterval(), [this]()
{
itsFlushStateTask = nullptr;
FlushOldData();
},
"ThreadsWidget::PauseBeforeFlushOldData",
true);
itsFlushStateTask->Start();
}
else if (sender == itsLink &&
(message.Is(Link::kProgramFinished) ||
message.Is(Link::kDetachedFromProcess)))
{
itsIsWaitingForReloadFlag = false;
Expand All @@ -371,6 +386,9 @@ ThreadsWidget::Receive

else if (sender == itsLink && message.Is(Link::kProgramStopped))
{
jdelete itsFlushStateTask;
itsFlushStateTask = nullptr;

// This is triggered when gdb prints file:line info.
// (It would be nice to avoid this if only the frame changed,
// but we can't merely set a flag when we get kFrameChanged
Expand Down
2 changes: 2 additions & 0 deletions code_medic/code/ThreadsWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <jx-af/jx/JXNamedTreeListWidget.h>

class JTree;
class JXIdleTask;
class Link;
class CommandDirector;
class ThreadsDir;
Expand Down Expand Up @@ -71,6 +72,7 @@ class ThreadsWidget : public JXNamedTreeListWidget
bool itsFlushWhenRunFlag;
JArray<JUInt64>* itsOpenIDList;
DisplayState itsDisplayState;
JXIdleTask* itsFlushStateTask;

private:

Expand Down
4 changes: 3 additions & 1 deletion code_medic/release/doc/ChangeLog.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ <h1>Code Medic: Changes from previous versions</h1>
<h2>7.2</h2>

<ul>
<li>When the program stops, opens both Threads and Stack Trace windows.</li>
<li>Threads and Stack Trace window no longer flicker when stepping through code.</li>

<li>When using lldb, it now maintains the thread you are stepping through.</li>

<li>When using gdb or lldb, it now displays the true type of every pointer. When a variable is transferred from the Local Variables window to the main Variables window, the object is cast to this type.</li>

<li>When the program stops at a location without a source file, opens both Threads and Stack Trace windows.</li>

<li>Removed "Display as C string" menu item because lldb backend now displays string contents.</li>

<li>Fixes for gdb data parsing.</li>
Expand Down

0 comments on commit 93ac973

Please sign in to comment.