Added check box to further group the wait objects by name. This allows to
easily see how wait times for similar objects add up. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34645 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
|
#include <CheckBox.h>
|
||||||
#include <GroupView.h>
|
#include <GroupView.h>
|
||||||
|
|
||||||
#include "table/TableColumns.h"
|
#include "table/TableColumns.h"
|
||||||
@@ -31,13 +32,26 @@ public:
|
|||||||
|
|
||||||
void SetModel(ModelType* model);
|
void SetModel(ModelType* model);
|
||||||
|
|
||||||
|
virtual void MessageReceived(BMessage* message);
|
||||||
|
|
||||||
|
virtual void AttachedToWindow();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class WaitObjectsTreeModel;
|
class WaitObjectsTreeModel;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MSG_ABSTRACT_WAIT_OBJECTS_GROUP_BY_NAME = 'awog'
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _UpdateTreeModel();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TreeTable* fWaitObjectsTree;
|
TreeTable* fWaitObjectsTree;
|
||||||
WaitObjectsTreeModel* fWaitObjectsTreeModel;
|
WaitObjectsTreeModel* fWaitObjectsTreeModel;
|
||||||
ModelType* fModel;
|
ModelType* fModel;
|
||||||
|
BCheckBox* fGroupByNameCheckBox;
|
||||||
|
bool fGroupByName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -48,12 +62,12 @@ ABSTRACT_WAIT_OBJECTS_PAGE_TEMPLATE
|
|||||||
class ABSTRACT_WAIT_OBJECTS_PAGE_CLASS::WaitObjectsTreeModel
|
class ABSTRACT_WAIT_OBJECTS_PAGE_CLASS::WaitObjectsTreeModel
|
||||||
: public TreeTableModel {
|
: public TreeTableModel {
|
||||||
public:
|
public:
|
||||||
WaitObjectsTreeModel(ModelType* model)
|
WaitObjectsTreeModel(ModelType* model, bool groupByName)
|
||||||
:
|
:
|
||||||
fModel(model),
|
fModel(model),
|
||||||
fRootNode(NULL)
|
fRootNode(NULL)
|
||||||
{
|
{
|
||||||
fRootNode = new RootNode(fModel);
|
fRootNode = new RootNode(fModel, groupByName);
|
||||||
}
|
}
|
||||||
|
|
||||||
~WaitObjectsTreeModel()
|
~WaitObjectsTreeModel()
|
||||||
@@ -90,9 +104,64 @@ private:
|
|||||||
struct Node {
|
struct Node {
|
||||||
virtual ~Node() {}
|
virtual ~Node() {}
|
||||||
|
|
||||||
|
virtual const char* Name() const = 0;
|
||||||
|
virtual uint32 Type() const = 0;
|
||||||
|
virtual addr_t Object() const = 0;
|
||||||
|
virtual addr_t ReferencedObject() const = 0;
|
||||||
|
virtual int64 Waits() const = 0;
|
||||||
|
virtual nanotime_t TotalWaitTime() const = 0;
|
||||||
|
|
||||||
virtual int32 CountChildren() const = 0;
|
virtual int32 CountChildren() const = 0;
|
||||||
virtual void* ChildAt(int32 index) const = 0;
|
virtual void* ChildAt(int32 index) const = 0;
|
||||||
virtual bool GetValueAt(int32 columnIndex, BVariant& value) = 0;
|
|
||||||
|
static int CompareByName(const Node* a, const Node* b)
|
||||||
|
{
|
||||||
|
int cmp = (int)a->Type() - (int)b->Type();
|
||||||
|
return cmp == 0 ? strcmp(a->Name(), b->Name()) : cmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetValueAt(int32 columnIndex, BVariant& value)
|
||||||
|
{
|
||||||
|
switch (columnIndex) {
|
||||||
|
case 0:
|
||||||
|
value.SetTo(wait_object_type_name(Type()),
|
||||||
|
B_VARIANT_DONT_COPY_DATA);
|
||||||
|
return true;
|
||||||
|
case 1:
|
||||||
|
value.SetTo(Name(), B_VARIANT_DONT_COPY_DATA);
|
||||||
|
return true;
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
addr_t object = Object();
|
||||||
|
if (object == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
char buffer[16];
|
||||||
|
snprintf(buffer, sizeof(buffer), "%#lx", object);
|
||||||
|
value.SetTo(buffer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
addr_t object = ReferencedObject();
|
||||||
|
if (object == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
char buffer[16];
|
||||||
|
snprintf(buffer, sizeof(buffer), "%#lx", object);
|
||||||
|
value.SetTo(buffer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
value.SetTo(Waits());
|
||||||
|
return true;
|
||||||
|
case 5:
|
||||||
|
value.SetTo(TotalWaitTime());
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ObjectNode : Node {
|
struct ObjectNode : Node {
|
||||||
@@ -104,6 +173,36 @@ private:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual const char* Name() const
|
||||||
|
{
|
||||||
|
return object->Name();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uint32 Type() const
|
||||||
|
{
|
||||||
|
return object->Type();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual addr_t Object() const
|
||||||
|
{
|
||||||
|
return object->Object();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual addr_t ReferencedObject() const
|
||||||
|
{
|
||||||
|
return object->ReferencedObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int64 Waits() const
|
||||||
|
{
|
||||||
|
return object->Waits();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual nanotime_t TotalWaitTime() const
|
||||||
|
{
|
||||||
|
return object->TotalWaitTime();
|
||||||
|
}
|
||||||
|
|
||||||
virtual int32 CountChildren() const
|
virtual int32 CountChildren() const
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -113,11 +212,6 @@ private:
|
|||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool GetValueAt(int32 columnIndex, BVariant& value)
|
|
||||||
{
|
|
||||||
return _GetWaitObjectValueAt(object, columnIndex, value);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// For GCC 2
|
// For GCC 2
|
||||||
@@ -139,6 +233,36 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual const char* Name() const
|
||||||
|
{
|
||||||
|
return group->Name();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uint32 Type() const
|
||||||
|
{
|
||||||
|
return group->Type();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual addr_t Object() const
|
||||||
|
{
|
||||||
|
return group->Object();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual addr_t ReferencedObject() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int64 Waits() const
|
||||||
|
{
|
||||||
|
return group->Waits();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual nanotime_t TotalWaitTime() const
|
||||||
|
{
|
||||||
|
return group->TotalWaitTime();
|
||||||
|
}
|
||||||
|
|
||||||
virtual int32 CountChildren() const
|
virtual int32 CountChildren() const
|
||||||
{
|
{
|
||||||
return objectNodes.CountItems();
|
return objectNodes.CountItems();
|
||||||
@@ -148,60 +272,136 @@ private:
|
|||||||
{
|
{
|
||||||
return objectNodes.ItemAt(index);
|
return objectNodes.ItemAt(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool GetValueAt(int32 columnIndex, BVariant& value)
|
|
||||||
{
|
|
||||||
if (columnIndex <= 2) {
|
|
||||||
return _GetWaitObjectValueAt(group->WaitObjectAt(0),
|
|
||||||
columnIndex, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (columnIndex) {
|
|
||||||
case 4:
|
|
||||||
value.SetTo(group->Waits());
|
|
||||||
return true;
|
|
||||||
case 5:
|
|
||||||
value.SetTo(group->TotalWaitTime());
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// For GCC 2
|
// For GCC 2
|
||||||
friend struct GroupNode;
|
friend struct GroupNode;
|
||||||
|
|
||||||
struct RootNode : Node {
|
struct NodeContainerNode : Node {
|
||||||
ModelType* model;
|
NodeContainerNode()
|
||||||
BObjectList<Node> groupNodes;
|
|
||||||
|
|
||||||
RootNode(ModelType* model)
|
|
||||||
:
|
:
|
||||||
model(model),
|
fChildren(20, true)
|
||||||
groupNodes(20, true)
|
|
||||||
{
|
{
|
||||||
int32 count = model->CountWaitObjectGroups();
|
}
|
||||||
for (int32 i = 0; i < count; i++) {
|
|
||||||
WaitObjectGroupType* group = model->WaitObjectGroupAt(i);
|
NodeContainerNode(BObjectList<Node>& nodes)
|
||||||
if (!groupNodes.AddItem(_CreateGroupNode(group)))
|
:
|
||||||
throw std::bad_alloc();
|
fChildren(20, true)
|
||||||
|
{
|
||||||
|
fChildren.AddList(&nodes);
|
||||||
|
|
||||||
|
// compute total waits and total wait time
|
||||||
|
fWaits = 0;
|
||||||
|
fTotalWaitTime = 0;
|
||||||
|
|
||||||
|
for (int32 i = 0; Node* node = fChildren.ItemAt(i); i++) {
|
||||||
|
fWaits += node->Waits();
|
||||||
|
fTotalWaitTime += node->TotalWaitTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual const char* Name() const
|
||||||
|
{
|
||||||
|
Node* child = fChildren.ItemAt(0);
|
||||||
|
return child != NULL ? child->Name() : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uint32 Type() const
|
||||||
|
{
|
||||||
|
Node* child = fChildren.ItemAt(0);
|
||||||
|
return child != NULL ? child->Type() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual addr_t Object() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual addr_t ReferencedObject() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int64 Waits() const
|
||||||
|
{
|
||||||
|
return fWaits;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual nanotime_t TotalWaitTime() const
|
||||||
|
{
|
||||||
|
return fTotalWaitTime;
|
||||||
|
}
|
||||||
|
|
||||||
virtual int32 CountChildren() const
|
virtual int32 CountChildren() const
|
||||||
{
|
{
|
||||||
return groupNodes.CountItems();
|
return fChildren.CountItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void* ChildAt(int32 index) const
|
virtual void* ChildAt(int32 index) const
|
||||||
{
|
{
|
||||||
return groupNodes.ItemAt(index);
|
return fChildren.ItemAt(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool GetValueAt(int32 columnIndex, BVariant& value)
|
protected:
|
||||||
|
BObjectList<Node> fChildren;
|
||||||
|
int64 fWaits;
|
||||||
|
nanotime_t fTotalWaitTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RootNode : public NodeContainerNode {
|
||||||
|
ModelType* model;
|
||||||
|
|
||||||
|
RootNode(ModelType* model, bool groupByName)
|
||||||
|
:
|
||||||
|
model(model)
|
||||||
{
|
{
|
||||||
return false;
|
// create nodes for the wait object groups
|
||||||
|
BObjectList<Node> tempChildren;
|
||||||
|
BObjectList<Node>& children
|
||||||
|
= groupByName ? tempChildren : NodeContainerNode::fChildren;
|
||||||
|
int32 count = model->CountWaitObjectGroups();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
WaitObjectGroupType* group = model->WaitObjectGroupAt(i);
|
||||||
|
if (!children.AddItem(_CreateGroupNode(group)))
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we shall group the nodes by name, we create grouping nodes.
|
||||||
|
if (groupByName) {
|
||||||
|
if (children.CountItems() < 2) {
|
||||||
|
NodeContainerNode::fChildren.AddList(&children);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort the nodes by name
|
||||||
|
children.SortItems(&Node::CompareByName);
|
||||||
|
|
||||||
|
// create groups
|
||||||
|
int32 nodeCount = children.CountItems();
|
||||||
|
BObjectList<Node> nameGroup;
|
||||||
|
Node* previousNode = children.ItemAt(0);
|
||||||
|
int32 groupNodeIndex = 0;
|
||||||
|
for (int32 i = 1; i < nodeCount; i++) {
|
||||||
|
Node* node = children.ItemAt(i);
|
||||||
|
if (strcmp(node->Name(), previousNode->Name())) {
|
||||||
|
// create the group -- or just add the node, if it's
|
||||||
|
// the only one
|
||||||
|
if (nameGroup.CountItems() > 1) {
|
||||||
|
NodeContainerNode::fChildren.AddItem(
|
||||||
|
new NodeContainerNode(nameGroup));
|
||||||
|
} else
|
||||||
|
NodeContainerNode::fChildren.AddItem(previousNode);
|
||||||
|
|
||||||
|
nameGroup.MakeEmpty();
|
||||||
|
groupNodeIndex = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the node
|
||||||
|
nameGroup.AddItem(node);
|
||||||
|
|
||||||
|
previousNode = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -213,54 +413,8 @@ private:
|
|||||||
|
|
||||||
return new GroupNode(group);
|
return new GroupNode(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
|
||||||
static bool _GetWaitObjectValueAt(WaitObjectType* waitObject,
|
|
||||||
int32 columnIndex, BVariant& value)
|
|
||||||
{
|
|
||||||
switch (columnIndex) {
|
|
||||||
case 0:
|
|
||||||
value.SetTo(wait_object_type_name(waitObject->Type()),
|
|
||||||
B_VARIANT_DONT_COPY_DATA);
|
|
||||||
return true;
|
|
||||||
case 1:
|
|
||||||
value.SetTo(waitObject->Name(), B_VARIANT_DONT_COPY_DATA);
|
|
||||||
return true;
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
if (waitObject->Object() == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
char buffer[16];
|
|
||||||
snprintf(buffer, sizeof(buffer), "%#lx",
|
|
||||||
waitObject->Object());
|
|
||||||
value.SetTo(buffer);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
if (waitObject->ReferencedObject() == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
char buffer[16];
|
|
||||||
snprintf(buffer, sizeof(buffer), "%#lx",
|
|
||||||
waitObject->ReferencedObject());
|
|
||||||
value.SetTo(buffer);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case 4:
|
|
||||||
value.SetTo(waitObject->Waits());
|
|
||||||
return true;
|
|
||||||
case 5:
|
|
||||||
value.SetTo(waitObject->TotalWaitTime());
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ModelType* fModel;
|
ModelType* fModel;
|
||||||
RootNode* fRootNode;
|
RootNode* fRootNode;
|
||||||
@@ -273,17 +427,24 @@ private:
|
|||||||
ABSTRACT_WAIT_OBJECTS_PAGE_TEMPLATE
|
ABSTRACT_WAIT_OBJECTS_PAGE_TEMPLATE
|
||||||
ABSTRACT_WAIT_OBJECTS_PAGE_CLASS::AbstractWaitObjectsPage()
|
ABSTRACT_WAIT_OBJECTS_PAGE_CLASS::AbstractWaitObjectsPage()
|
||||||
:
|
:
|
||||||
BGroupView(B_VERTICAL),
|
BGroupView(B_VERTICAL, 10),
|
||||||
fWaitObjectsTree(NULL),
|
fWaitObjectsTree(NULL),
|
||||||
fWaitObjectsTreeModel(NULL),
|
fWaitObjectsTreeModel(NULL),
|
||||||
fModel(NULL)
|
fModel(NULL),
|
||||||
|
fGroupByNameCheckBox(NULL),
|
||||||
|
fGroupByName(false)
|
||||||
{
|
{
|
||||||
SetName("Wait Objects");
|
SetName("Wait Objects");
|
||||||
|
|
||||||
fWaitObjectsTree = new TreeTable("wait object list", 0);
|
fWaitObjectsTree = new TreeTable("wait object list", 0);
|
||||||
AddChild(fWaitObjectsTree->ToView());
|
AddChild(fWaitObjectsTree->ToView());
|
||||||
|
|
||||||
|
fGroupByNameCheckBox = new BCheckBox("group by name checkbox",
|
||||||
|
"Group by Name", new BMessage(MSG_ABSTRACT_WAIT_OBJECTS_GROUP_BY_NAME));
|
||||||
|
fGroupByNameCheckBox->SetValue(
|
||||||
|
fGroupByName ? B_CONTROL_ON : B_CONTROL_OFF);
|
||||||
|
AddChild(fGroupByNameCheckBox);
|
||||||
|
|
||||||
fWaitObjectsTree->AddColumn(new StringTableColumn(0, "Type", 80, 40, 1000,
|
fWaitObjectsTree->AddColumn(new StringTableColumn(0, "Type", 80, 40, 1000,
|
||||||
B_TRUNCATE_END, B_ALIGN_LEFT));
|
B_TRUNCATE_END, B_ALIGN_LEFT));
|
||||||
fWaitObjectsTree->AddColumn(new StringTableColumn(1, "Name", 80, 40, 1000,
|
fWaitObjectsTree->AddColumn(new StringTableColumn(1, "Name", 80, 40, 1000,
|
||||||
@@ -324,9 +485,49 @@ ABSTRACT_WAIT_OBJECTS_PAGE_CLASS::SetModel(ModelType* model)
|
|||||||
|
|
||||||
fModel = model;
|
fModel = model;
|
||||||
|
|
||||||
|
if (fModel != NULL)
|
||||||
|
_UpdateTreeModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ABSTRACT_WAIT_OBJECTS_PAGE_TEMPLATE
|
||||||
|
void
|
||||||
|
ABSTRACT_WAIT_OBJECTS_PAGE_CLASS::MessageReceived(BMessage* message)
|
||||||
|
{
|
||||||
|
switch (message->what) {
|
||||||
|
case MSG_ABSTRACT_WAIT_OBJECTS_GROUP_BY_NAME:
|
||||||
|
fGroupByName = fGroupByNameCheckBox->Value() == B_CONTROL_ON;
|
||||||
|
_UpdateTreeModel();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BGroupView::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ABSTRACT_WAIT_OBJECTS_PAGE_TEMPLATE
|
||||||
|
void
|
||||||
|
ABSTRACT_WAIT_OBJECTS_PAGE_CLASS::AttachedToWindow()
|
||||||
|
{
|
||||||
|
fGroupByNameCheckBox->SetTarget(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ABSTRACT_WAIT_OBJECTS_PAGE_TEMPLATE
|
||||||
|
void
|
||||||
|
ABSTRACT_WAIT_OBJECTS_PAGE_CLASS::_UpdateTreeModel()
|
||||||
|
{
|
||||||
|
if (fModel != NULL) {
|
||||||
|
fWaitObjectsTree->SetTreeTableModel(NULL);
|
||||||
|
delete fWaitObjectsTreeModel;
|
||||||
|
fWaitObjectsTreeModel = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (fModel != NULL) {
|
if (fModel != NULL) {
|
||||||
try {
|
try {
|
||||||
fWaitObjectsTreeModel = new WaitObjectsTreeModel(fModel);
|
fWaitObjectsTreeModel = new WaitObjectsTreeModel(fModel,
|
||||||
|
fGroupByName);
|
||||||
} catch (std::bad_alloc) {
|
} catch (std::bad_alloc) {
|
||||||
// TODO: Report error!
|
// TODO: Report error!
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user