* Added ThreadModel, which holds additional information on a thread, and

ThreadModelLoader to prepare the model.
* Changed the wait objects page in the thread window to display the wait objects
  grouped by type and name.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30429 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2009-04-26 15:42:49 +00:00
parent b592dac021
commit ded186e9e0
10 changed files with 519 additions and 41 deletions

View File

@ -14,7 +14,9 @@
#include <AutoLocker.h>
//#include "MessageCodes.h"
#include "MessageCodes.h"
#include "ThreadModel.h"
#include "ThreadModelLoader.h"
#include "thread_window/GeneralPage.h"
#include "thread_window/WaitObjectsPage.h"
@ -40,7 +42,9 @@ ThreadWindow::ThreadWindow(SubWindowManager* manager, Model* model,
fGeneralPage(NULL),
fWaitObjectsPage(NULL),
fModel(model),
fThread(thread)
fThread(thread),
fThreadModel(NULL),
fThreadModelLoader(NULL)
{
BGroupLayout* rootLayout = new BGroupLayout(B_VERTICAL);
SetLayout(rootLayout);
@ -54,13 +58,92 @@ ThreadWindow::ThreadWindow(SubWindowManager* manager, Model* model,
fMainTabView->AddTab(fWaitObjectsPage = new WaitObjectsPage);
fGeneralPage->SetModel(fModel, fThread);
fWaitObjectsPage->SetModel(fModel, fThread);
fModel->AddReference();
// create a thread model loader
fThreadModelLoader = new ThreadModelLoader(fModel, fThread,
BMessenger(this), NULL);
}
ThreadWindow::~ThreadWindow()
{
if (fThreadModelLoader != NULL)
fThreadModelLoader->Delete();
delete fThreadModel;
fModel->RemoveReference();
}
void
ThreadWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_MODEL_LOADED_SUCCESSFULLY:
{
printf("MSG_MODEL_LOADED_SUCCESSFULLY\n");
ThreadModel* model = fThreadModelLoader->DetachModel();
fThreadModelLoader->Delete();
fThreadModelLoader = NULL;
_SetModel(model);
break;
}
case MSG_MODEL_LOADED_FAILED:
case MSG_MODEL_LOADED_ABORTED:
{
printf("MSG_MODEL_LOADED_FAILED/MSG_MODEL_LOADED_ABORTED\n");
fThreadModelLoader->Delete();
fThreadModelLoader = NULL;
// TODO: User feedback (in failed case)!
break;
}
default:
SubWindow::MessageReceived(message);
break;
}
}
void
ThreadWindow::Quit()
{
if (fThreadModelLoader != NULL)
fThreadModelLoader->Abort(true);
SubWindow::Quit();
}
void
ThreadWindow::Show()
{
SubWindow::Show();
AutoLocker<ThreadWindow> locker;
if (fThreadModelLoader == NULL)
return;
status_t error = fThreadModelLoader->StartLoading();
if (error != B_OK) {
fThreadModelLoader->Delete();
fThreadModelLoader = NULL;
// TODO: User feedback!
}
}
void
ThreadWindow::_SetModel(ThreadModel* model)
{
delete fThreadModel;
fThreadModel = model;
fWaitObjectsPage->SetModel(fThreadModel);
}

View File

@ -10,6 +10,8 @@
class BTabView;
class ThreadModel;
class ThreadModelLoader;
class ThreadWindow : public SubWindow {
@ -18,18 +20,17 @@ public:
Model* model, Model::Thread* thread);
virtual ~ThreadWindow();
// virtual void MessageReceived(BMessage* message);
virtual void MessageReceived(BMessage* message);
// virtual void Quit();
// virtual void Show();
virtual void Quit();
virtual void Show();
private:
class GeneralPage;
class WaitObjectsPage;
private:
void _SetModel(Model* model);
void _SetModel(ThreadModel* model);
private:
BTabView* fMainTabView;
@ -37,6 +38,8 @@ private:
WaitObjectsPage* fWaitObjectsPage;
Model* fModel;
Model::Thread* fThread;
ThreadModel* fThreadModel;
ThreadModelLoader* fThreadModelLoader;
};

View File

@ -11,6 +11,8 @@
#include <thread_defs.h>
#include "ThreadModel.h"
#include "table/TableColumns.h"
@ -20,13 +22,12 @@
class ThreadWindow::WaitObjectsPage::WaitObjectsTreeModel
: public TreeTableModel {
public:
WaitObjectsTreeModel(Model* model, Model::Thread* thread)
WaitObjectsTreeModel(ThreadModel* model)
:
fModel(model),
fThread(thread),
fThreadModel(model),
fRootNode(NULL)
{
fRootNode = new RootNode(thread);
fRootNode = new RootNode(fThreadModel);
}
~WaitObjectsTreeModel()
@ -98,20 +99,17 @@ private:
friend struct ObjectNode;
struct GroupNode : Node {
Model::ThreadWaitObjectGroup* group;
ThreadModel::WaitObjectGroup* group;
BObjectList<ObjectNode> objectNodes;
GroupNode(Model::ThreadWaitObjectGroup* group)
GroupNode(ThreadModel::WaitObjectGroup* group)
:
group(group)
{
BObjectList<Model::ThreadWaitObject> objects;
if (!group->GetThreadWaitObjects(objects))
throw std::bad_alloc();
int32 count = objects.CountItems();
int32 count = group->CountWaitObjects();
for (int32 i = 0; i < count; i++) {
if (!objectNodes.AddItem(new ObjectNode(objects.ItemAt(i))))
Model::ThreadWaitObject* waitObject = group->WaitObjectAt(i);
if (!objectNodes.AddItem(new ObjectNode(waitObject)))
throw std::bad_alloc();
}
}
@ -131,7 +129,8 @@ private:
if (columnIndex >= 3)
return false;
return _GetWaitObjectValueAt(group->MostRecentWaitObject(),
return _GetWaitObjectValueAt(
group->WaitObjectAt(0)->GetWaitObject(),
columnIndex, value);
}
};
@ -140,18 +139,18 @@ private:
friend struct GroupNode;
struct RootNode : Node {
Model::Thread* thread;
ThreadModel* threadModel;
BObjectList<GroupNode> groupNodes;
RootNode(Model::Thread* thread)
RootNode(ThreadModel* model)
:
thread(thread),
threadModel(model),
groupNodes(20, true)
{
int32 count = thread->CountThreadWaitObjectGroups();
int32 count = threadModel->CountWaitObjectGroups();
for (int32 i = 0; i < count; i++) {
Model::ThreadWaitObjectGroup* group
= thread->ThreadWaitObjectGroupAt(i);
ThreadModel::WaitObjectGroup* group
= threadModel->WaitObjectGroupAt(i);
if (!groupNodes.AddItem(new GroupNode(group)))
throw std::bad_alloc();
}
@ -235,8 +234,7 @@ private:
}
private:
Model* fModel;
Model::Thread* fThread;
ThreadModel* fThreadModel;
RootNode* fRootNode;
};
@ -249,7 +247,7 @@ ThreadWindow::WaitObjectsPage::WaitObjectsPage()
BGroupView(B_VERTICAL),
fWaitObjectsTree(NULL),
fWaitObjectsTreeModel(NULL),
fModel(NULL)
fThreadModel(NULL)
{
SetName("Wait Objects");
@ -278,24 +276,22 @@ ThreadWindow::WaitObjectsPage::~WaitObjectsPage()
void
ThreadWindow::WaitObjectsPage::SetModel(Model* model, Model::Thread* thread)
ThreadWindow::WaitObjectsPage::SetModel(ThreadModel* model)
{
if (model == fModel)
if (model == fThreadModel)
return;
if (fModel != NULL) {
if (fThreadModel != NULL) {
fWaitObjectsTree->SetTreeTableModel(NULL);
delete fWaitObjectsTreeModel;
fWaitObjectsTreeModel = NULL;
}
fModel = model;
fThread = thread;
fThreadModel = model;
if (fModel != NULL) {
if (fThreadModel != NULL) {
try {
fWaitObjectsTreeModel
= new WaitObjectsTreeModel(fModel, fThread);
fWaitObjectsTreeModel = new WaitObjectsTreeModel(fThreadModel);
} catch (std::bad_alloc) {
// TODO: Report error!
}

View File

@ -18,7 +18,7 @@ public:
WaitObjectsPage();
virtual ~WaitObjectsPage();
void SetModel(Model* model, Model::Thread* thread);
void SetModel(ThreadModel* model);
private:
class WaitObjectsTreeModel;
@ -31,8 +31,7 @@ private:
private:
TreeTable* fWaitObjectsTree;
WaitObjectsTreeModel* fWaitObjectsTreeModel;
Model* fModel;
Model::Thread* fThread;
ThreadModel* fThreadModel;
};

View File

@ -9,4 +9,5 @@ UseHeaders $(HAIKU_DEBUG_ANALYZER_HEADERS) ;
MergeObject DebugAnalyzer_model.o
:
Model.cpp
ThreadModel.cpp
;

View File

@ -0,0 +1,78 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "ThreadModel.h"
#include <new>
// #pragma mark - WaitObjectGroup
ThreadModel::WaitObjectGroup::WaitObjectGroup(
Model::ThreadWaitObject** waitObjects, int32 count)
:
fWaitObjects(waitObjects),
fCount(count)
{
}
ThreadModel::WaitObjectGroup::~WaitObjectGroup()
{
}
// #pragma mark - ThreadModel
ThreadModel::ThreadModel(Model* model, Model::Thread* thread)
:
fModel(model),
fThread(thread),
fWaitObjectGroups(10, true)
{
}
ThreadModel::~ThreadModel()
{
}
ThreadModel::WaitObjectGroup*
ThreadModel::AddWaitObjectGroup(
const BObjectList<Model::ThreadWaitObject>& waitObjects, int32 start,
int32 end)
{
// check params
int32 count = end - start;
if (start < 0 || count <= 0 || waitObjects.CountItems() < end)
return NULL;
// create an array of the wait object
Model::ThreadWaitObject** objects
= new(std::nothrow) Model::ThreadWaitObject*[count];
if (objects == NULL)
return NULL;
for (int32 i = 0; i < count; i++)
objects[i] = waitObjects.ItemAt(start + i);
// create and add the group
WaitObjectGroup* group = new(std::nothrow) WaitObjectGroup(objects, count);
if (group == NULL) {
delete[] objects;
return NULL;
}
if (!fWaitObjectGroups.BinaryInsert(group,
&WaitObjectGroup::CompareByTypeName)) {
delete group;
return NULL;
}
return group;
}

View File

@ -0,0 +1,144 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef THREAD_MODEL_H
#define THREAD_MODEL_H
#include <string.h>
#include "Model.h"
class ThreadModel {
public:
struct type_and_name;
class WaitObjectGroup;
public:
ThreadModel(Model* model,
Model::Thread* thread);
~ThreadModel();
Model* GetModel() const { return fModel; }
Model::Thread* GetThread() const { return fThread; }
WaitObjectGroup* AddWaitObjectGroup(
const BObjectList<Model::ThreadWaitObject>&
waitObjects,
int32 start, int32 end);
inline int32 CountWaitObjectGroups() const;
inline WaitObjectGroup* WaitObjectGroupAt(int32 index) const;
private:
typedef BObjectList<WaitObjectGroup> WaitObjectGroupList;
private:
Model* fModel;
Model::Thread* fThread;
WaitObjectGroupList fWaitObjectGroups;
};
struct ThreadModel::type_and_name {
uint32 type;
const char* name;
};
class ThreadModel::WaitObjectGroup {
public:
WaitObjectGroup(
Model::ThreadWaitObject** waitObjects,
int32 count);
~WaitObjectGroup();
inline uint32 Type() const;
inline const char* Name() const;
inline int32 CountWaitObjects() const;
inline Model::ThreadWaitObject* WaitObjectAt(int32 index) const;
static inline int CompareByTypeName(const WaitObjectGroup* a,
const WaitObjectGroup* b);
static inline int CompareWithTypeName(
const type_and_name* key,
const WaitObjectGroup* group);
private:
Model::ThreadWaitObject** fWaitObjects;
int32 fCount;
};
// #pragma mark - ThreadModel
int32
ThreadModel::CountWaitObjectGroups() const
{
return fWaitObjectGroups.CountItems();
}
ThreadModel::WaitObjectGroup*
ThreadModel::WaitObjectGroupAt(int32 index) const
{
return fWaitObjectGroups.ItemAt(index);
}
// #pragma mark - WaitObjectGroup
uint32
ThreadModel::WaitObjectGroup::Type() const
{
return fWaitObjects[0]->Type();
}
const char*
ThreadModel::WaitObjectGroup::Name() const
{
return fWaitObjects[0]->Name();
}
int32
ThreadModel::WaitObjectGroup::CountWaitObjects() const
{
return fCount;
}
Model::ThreadWaitObject*
ThreadModel::WaitObjectGroup::WaitObjectAt(int32 index) const
{
return index >= 0 && index < fCount ? fWaitObjects[0] : NULL;
}
/*static*/ int
ThreadModel::WaitObjectGroup::CompareByTypeName(const WaitObjectGroup* a,
const WaitObjectGroup* b)
{
type_and_name key;
key.type = a->Type();
key.name = a->Name();
return CompareWithTypeName(&key, b);
}
/*static*/ int
ThreadModel::WaitObjectGroup::CompareWithTypeName(const type_and_name* key,
const WaitObjectGroup* group)
{
if (key->type != group->Type())
return key->type < group->Type() ? -1 : 1;
return strcmp(key->name, group->Name());
}
#endif // THREAD_MODEL_h

View File

@ -10,4 +10,5 @@ MergeObject DebugAnalyzer_model_loader.o
:
AbstractModelLoader.cpp
ModelLoader.cpp
ThreadModelLoader.cpp
;

View File

@ -0,0 +1,130 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "ThreadModelLoader.h"
#include <new>
#include <AutoLocker.h>
#include "ThreadModel.h"
static int
compare_by_type_and_name(const Model::ThreadWaitObject* a,
const Model::ThreadWaitObject* b)
{
if (a->Type() != b->Type())
return a->Type() < b->Type() ? -1 : 1;
return strcmp(a->Name(), b->Name());
}
// #pragma mark -
ThreadModelLoader::ThreadModelLoader(Model* model, Model::Thread* thread,
const BMessenger& target, void* targetCookie)
:
AbstractModelLoader(target, targetCookie),
fModel(model),
fThread(thread),
fThreadModel(NULL)
{
}
ThreadModelLoader::~ThreadModelLoader()
{
delete fThreadModel;
}
ThreadModel*
ThreadModelLoader::DetachModel()
{
AutoLocker<BLocker> locker(fLock);
if (fThreadModel == NULL || fLoading)
return NULL;
ThreadModel* model = fThreadModel;
fThreadModel = NULL;
return model;
}
status_t
ThreadModelLoader::PrepareForLoading()
{
return B_OK;
}
status_t
ThreadModelLoader::Load()
{
try {
return _Load();
} catch(...) {
return B_ERROR;
}
}
void
ThreadModelLoader::FinishLoading(bool success)
{
if (!success) {
delete fThreadModel;
fThreadModel = NULL;
}
}
status_t
ThreadModelLoader::_Load()
{
// create a model
fThreadModel = new(std::nothrow) ThreadModel(fModel, fThread);
if (fThreadModel == NULL)
return B_NO_MEMORY;
// collect all wait objects
BObjectList<Model::ThreadWaitObject> waitObjects;
int32 groupCount = fThread->CountThreadWaitObjectGroups();
for (int32 i = 0; i < groupCount; i++) {
Model::ThreadWaitObjectGroup* group
= fThread->ThreadWaitObjectGroupAt(i);
if (!group->GetThreadWaitObjects(waitObjects))
return B_NO_MEMORY;
}
// sort them by type and name
waitObjects.SortItems(&compare_by_type_and_name);
// create the groups
int32 count = waitObjects.CountItems();
for (int32 i = 0; i < count; i++) {
// collect the objects for this group
Model::ThreadWaitObject* firstObject = waitObjects.ItemAt(i);
int32 k = i + 1;
for (; k < count; k++) {
if (compare_by_type_and_name(firstObject, waitObjects.ItemAt(k))
!= 0) {
break;
}
}
if (fThreadModel->AddWaitObjectGroup(waitObjects, i, k) == NULL)
return B_NO_MEMORY;
}
return B_OK;
}

View File

@ -0,0 +1,43 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef THREAD_MODEL_LOADER_H
#define THREAD_MODEL_LOADER_H
#include "AbstractModelLoader.h"
#include "Model.h"
class ThreadModel;
class ThreadModelLoader : public AbstractModelLoader {
public:
ThreadModelLoader(Model* model,
Model::Thread* thread,
const BMessenger& target,
void* targetCookie);
protected:
~ThreadModelLoader();
public:
ThreadModel* DetachModel();
protected:
virtual status_t PrepareForLoading();
virtual status_t Load();
virtual void FinishLoading(bool success);
private:
status_t _Load();
private:
Model* fModel;
Model::Thread* fThread;
ThreadModel* fThreadModel;
};
#endif // THREAD_MODEL_LOADER_H