Browse Source

Parallel Stacks v0.3

pull/15/head
Eusebiu Marcu 15 years ago
parent
commit
a860840709
  1. 117
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs
  2. 122
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs

117
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs

@ -23,9 +23,11 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -23,9 +23,11 @@ namespace Debugger.AddIn.Pads.ParallelPad
{
private DrawSurface surface;
private Process debuggedProcess;
private ParallelStacksGraph graph;
private List<ThreadStack> currentThreadStacks = new List<ThreadStack>();
#region Overrides
protected override void InitializeComponents()
{
surface = new DrawSurface();
@ -52,16 +54,6 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -52,16 +54,6 @@ namespace Debugger.AddIn.Pads.ParallelPad
RefreshPad();
}
void OnReset(object sender, EventArgs e)
{
currentThreadStacks.Clear();
}
void debuggedProcess_Paused(object sender, ProcessEventArgs e)
{
RefreshPad();
}
public override void RefreshPad()
{
@ -101,7 +93,7 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -101,7 +93,7 @@ namespace Debugger.AddIn.Pads.ParallelPad
if (stack == null)
continue;
if (stack.ThreadStackParent != null &&
(stack.ThreadStackChildren == null || stack.ThreadStackChildren.Length == 0))
(stack.ThreadStackChildren == null || stack.ThreadStackChildren.Count == 0))
continue;
graph.AddVertex(stack);
@ -113,12 +105,24 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -113,12 +105,24 @@ namespace Debugger.AddIn.Pads.ParallelPad
surface.SetGraph(graph);
}
}
#endregion
#region Private Methods
ParallelStacksGraph graph;
private void OnReset(object sender, EventArgs e)
{
currentThreadStacks.Clear();
}
private void debuggedProcess_Paused(object sender, ProcessEventArgs e)
{
RefreshPad();
}
void AddChildren(ThreadStack parent)
private void AddChildren(ThreadStack parent)
{
if(parent.ThreadStackChildren == null || parent.ThreadStackChildren.Length == 0)
if(parent.ThreadStackChildren == null || parent.ThreadStackChildren.Count == 0)
return;
foreach (var ts in parent.ThreadStackChildren)
@ -128,7 +132,7 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -128,7 +132,7 @@ namespace Debugger.AddIn.Pads.ParallelPad
graph.AddVertex(ts);
graph.AddEdge(new ParallelStacksEdge(parent, ts));
if (ts.ThreadStackChildren == null || ts.ThreadStackChildren.Length == 0)
if (ts.ThreadStackChildren == null || ts.ThreadStackChildren.Count == 0)
continue;
AddChildren(ts);
@ -160,7 +164,7 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -160,7 +164,7 @@ namespace Debugger.AddIn.Pads.ParallelPad
foreach (var stack in currentThreadStacks) {
int count = stack.ItemCollection.Count;
dynamic frame = stack.ItemCollection[count - 1];
string fullname = frame.MethodName;
string fullname = frame.MethodName + stack.Level.ToString();
if (!commonFrameThreads.ContainsKey(fullname))
commonFrameThreads.Add(fullname, new List<ThreadStack>());
@ -217,7 +221,7 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -217,7 +221,7 @@ namespace Debugger.AddIn.Pads.ParallelPad
// remove last [frameIndex] and create a new ThreadStack as the parent of what remained in the children
var threadIds = new List<uint>();
var parentItems = new Stack<ExpandoObject>();
int j = 0;
while (frameIndex > 0) {
for (int i = 0 ; i < listOfCurrentStacks.Count; ++i) {
var stack = listOfCurrentStacks[i];
@ -229,24 +233,31 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -229,24 +233,31 @@ namespace Debugger.AddIn.Pads.ParallelPad
#endif
if (i == 0)
parentItems.Push(stack.ItemCollection[indexToRemove]);
if (i == j)
threadIds.AddRange(stack.ThreadIds);
stack.ItemCollection.RemoveAt(indexToRemove);
}
j++;
frameIndex--;
}
// update thread ids
for (int i = 0 ; i < listOfCurrentStacks.Count; ++i)
threadIds.AddRange(listOfCurrentStacks[i].ThreadIds);
// remove stacks with no items
for (int i = listOfCurrentStacks.Count - 1; i >= 0; --i) {
var stack = listOfCurrentStacks[i];
if (stack.ItemCollection.Count == 0)
listOfCurrentStacks.Remove(stack);
}
// increase the Level
for (int i = 0 ; i < listOfCurrentStacks.Count; ++i)
listOfCurrentStacks[i].Level++;
// create new parent stack
ThreadStack commonParent = new ThreadStack();
commonParent.ThreadIds = threadIds;
commonParent.UpdateThreadIds(threadIds.ToArray());
commonParent.ItemCollection = parentItems.ToObservable();
commonParent.Process = debuggedProcess;
commonParent.FrameSelected += threadStack_FrameSelected;
@ -259,15 +270,48 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -259,15 +270,48 @@ namespace Debugger.AddIn.Pads.ParallelPad
continue;
}
dynamic item = stack.ItemCollection[stack.ItemCollection.Count - 1];
// add the parent to the parent
if (stack.ThreadStackParent != null) {
// remove stack from it's parent because it will have the commonParent as parent
stack.ThreadStackParent.ThreadStackChildren.Remove(stack);
commonParent.ThreadStackParent = stack.ThreadStackParent;
commonParent.ThreadStackParent.ThreadStackChildren.Add(commonParent);
// set level
commonParent.Level = stack.Level - 1;
}
// update thread ids
var parent = commonParent.ThreadStackParent;
if (parent != null) {
if (parent.ThreadIds != null)
{
var list = new List<uint>();
foreach (uint id in commonParent.ThreadIds) {
if (!parent.ThreadIds.Contains(id)) {
list.Add(id);
}
}
parent.UpdateThreadIds(list.ToArray());
}
}
stack.ThreadStackParent = commonParent;
string currentName = item.MethodName;
var newList = new List<ThreadStack>();
newList.Add(stack);
string currentName = item.MethodName + stack.Level.ToString();;
commonFrameThreads.Add(currentName, newList);
// add name or add to list
if (!commonFrameThreads.ContainsKey(currentName)) {
var newList = new List<ThreadStack>();
newList.Add(stack);
commonFrameThreads.Add(currentName, newList);
}
else {
var list = commonFrameThreads[currentName];
list.Add(stack);
}
}
commonParent.ThreadStackChildren = listOfCurrentStacks.ToArray();
commonParent.ThreadStackChildren = listOfCurrentStacks.Clone();
commonFrameThreads[frameName].Clear();
commonFrameThreads[frameName].Add(commonParent);
currentThreadStacks.Add(commonParent);
@ -289,8 +333,7 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -289,8 +333,7 @@ namespace Debugger.AddIn.Pads.ParallelPad
ThreadStack threadStack = new ThreadStack();
threadStack.FrameSelected += threadStack_FrameSelected;
threadStack.ThreadIds = new List<uint>();
threadStack.ThreadIds.Add(thread.ID);
threadStack.UpdateThreadIds(thread.ID);
threadStack.Process = debuggedProcess;
currentThreadStacks.Add(threadStack);
@ -299,7 +342,7 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -299,7 +342,7 @@ namespace Debugger.AddIn.Pads.ParallelPad
threadStack.IsSelected = threadStack.ThreadIds.Contains(debuggedProcess.SelectedThread.ID);
}
void threadStack_FrameSelected(object sender, EventArgs e)
private void threadStack_FrameSelected(object sender, EventArgs e)
{
foreach (var ts in this.currentThreadStacks) {
ts.IsSelected = false;
@ -346,6 +389,8 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -346,6 +389,8 @@ namespace Debugger.AddIn.Pads.ParallelPad
return result;
}
#endregion
}
internal static class StackFrameExtensions
@ -366,6 +411,18 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -366,6 +411,18 @@ namespace Debugger.AddIn.Pads.ParallelPad
internal static class ParallelStackExtensions
{
internal static List<T> Clone<T>(this List<T> listToClone)
{
if (listToClone == null)
return null;
List<T> result = new List<T>();
foreach (var item in listToClone)
result.Add(item);
return result;
}
internal static ObservableCollection<T> ToObservable<T>(this Stack<T> stack)
{
if (stack == null)

122
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Dynamic;
using System.Windows;
using System.Windows.Controls;
@ -25,22 +26,28 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -25,22 +26,28 @@ namespace Debugger.AddIn.Pads.ParallelPad
DependencyProperty.Register("IsSelected", typeof(bool), typeof(ThreadStack),
new FrameworkPropertyMetadata());
public event EventHandler FrameSelected;
private ObservableCollection<ExpandoObject> itemCollection = new ObservableCollection<ExpandoObject>();
private ToolTip toolTip = new ToolTip();
private List<uint> threadIds = new List<uint>();
public ThreadStack()
{
InitializeComponent();
ToolTip = toolTip;
ToolTipOpening += new ToolTipEventHandler(OnToolTipOpening);
datagrid.ToolTip = toolTip;
datagrid.ToolTipOpening += OnToolTipOpening;
datagrid.PreviewMouseMove += new MouseEventHandler(datagrid_PreviewMouseMove);
datagrid.MouseLeave += delegate { toolTip.IsOpen = false; };
}
#region Public Properties
public Process Process { get; set; }
public int Level { get; set; }
public bool IsSelected {
get { return (bool)GetValue(IsSelectedProperty); }
set {
@ -61,9 +68,13 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -61,9 +68,13 @@ namespace Debugger.AddIn.Pads.ParallelPad
public ThreadStack ThreadStackParent { get; set; }
public ThreadStack[] ThreadStackChildren { get; set; }
public List<ThreadStack> ThreadStackChildren { get; set; }
public List<uint> ThreadIds { get; set; }
public List<uint> ThreadIds {
get {
return threadIds;
}
}
public ObservableCollection<ExpandoObject> ItemCollection {
get {
@ -73,14 +84,23 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -73,14 +84,23 @@ namespace Debugger.AddIn.Pads.ParallelPad
set {
itemCollection = value;
this.datagrid.ItemsSource = itemCollection;
if (ThreadIds.Count > 1)
this.HeaderText.Text = ThreadIds.Count.ToString() + " Threads";
else
this.HeaderText.Text = "1 Thread";
}
}
#endregion
#region Public Methods
public void UpdateThreadIds(params uint[] threadIds)
{
this.threadIds.AddRange(threadIds);
if (this.threadIds.Count > 1)
this.HeaderText.Text = this.threadIds.Count.ToString() + " Threads";
else
this.HeaderText.Text = "1 Thread";
}
public void ClearImages()
{
foreach(dynamic item in itemCollection) {
@ -88,7 +108,11 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -88,7 +108,11 @@ namespace Debugger.AddIn.Pads.ParallelPad
}
}
void SelectParent(bool isSelected)
#endregion
#region Private Methods
private void SelectParent(bool isSelected)
{
var ts = this.ThreadStackParent;
while(ts != null) {
@ -97,7 +121,24 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -97,7 +121,24 @@ namespace Debugger.AddIn.Pads.ParallelPad
}
}
void Datagrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
void datagrid_PreviewMouseMove(object sender, MouseEventArgs e)
{
var result = VisualTreeHelper.HitTest(this, e.GetPosition(this));
if (result != null)
{
var row = TryFindParent<DataGridRow>(result.VisualHit);
if (row != null)
{
datagrid.SelectedItem = row.DataContext;
if (toolTip.IsOpen)
toolTip.IsOpen = false;
toolTip.IsOpen = true;
e.Handled = true;
}
}
}
private void Datagrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (Process.IsRunning) return;
@ -114,7 +155,7 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -114,7 +155,7 @@ namespace Debugger.AddIn.Pads.ParallelPad
}
}
void SelectFrame(uint threadId, ExpandoObject selectedItem)
private void SelectFrame(uint threadId, ExpandoObject selectedItem)
{
if (selectedItem == null)
return;
@ -142,7 +183,7 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -142,7 +183,7 @@ namespace Debugger.AddIn.Pads.ParallelPad
}
}
void Datagrid_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
private void Datagrid_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
if (Process.IsRunning) return;
@ -154,7 +195,7 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -154,7 +195,7 @@ namespace Debugger.AddIn.Pads.ParallelPad
datagrid.ContextMenu.IsOpen = true;
}
ContextMenu CreateContextMenu(ExpandoObject item)
private ContextMenu CreateContextMenu(ExpandoObject item)
{
dynamic obj = item;
@ -177,7 +218,7 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -177,7 +218,7 @@ namespace Debugger.AddIn.Pads.ParallelPad
return menu;
}
void OnToolTipOpening(object sender, ToolTipEventArgs e)
private void OnToolTipOpening(object sender, ToolTipEventArgs e)
{
StackPanel panel = new StackPanel();
@ -196,7 +237,6 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -196,7 +237,6 @@ namespace Debugger.AddIn.Pads.ParallelPad
{
if (selectedItem.MethodName == frame.GetMethodName())
{
// TODO : get method parameter values
TextBlock tb = new TextBlock();
tb.Text = thread.ID + ": " + CallStackPadContent.GetFullName(frame);
panel.Children.Add(tb);
@ -207,5 +247,53 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -207,5 +247,53 @@ namespace Debugger.AddIn.Pads.ParallelPad
this.toolTip.Content = panel;
}
#endregion
#region Static Methods
private static T TryFindParent<T>(DependencyObject child) where T : DependencyObject
{
if (child is T) return child as T;
DependencyObject parentObject = GetParentObject(child);
if (parentObject == null) return null;
var parent = parentObject as T;
if (parent != null && parent is T)
{
return parent;
}
else
{
return TryFindParent<T>(parentObject);
}
}
private static DependencyObject GetParentObject(DependencyObject child)
{
if (child == null) return null;
ContentElement contentElement = child as ContentElement;
if (contentElement != null)
{
DependencyObject parent = ContentOperations.GetParent(contentElement);
if (parent != null) return parent;
FrameworkContentElement fce = contentElement as FrameworkContentElement;
return fce != null ? fce.Parent : null;
}
FrameworkElement frameworkElement = child as FrameworkElement;
if (frameworkElement != null)
{
DependencyObject parent = frameworkElement.Parent;
if (parent != null) return parent;
}
return VisualTreeHelper.GetParent(child);
}
#endregion
}
}
Loading…
Cancel
Save