diff --git a/src/apps/debuganalyzer/gui/thread_window/ThreadWindow.cpp b/src/apps/debuganalyzer/gui/thread_window/ThreadWindow.cpp index b140c548fd..f00a1be0ea 100644 --- a/src/apps/debuganalyzer/gui/thread_window/ThreadWindow.cpp +++ b/src/apps/debuganalyzer/gui/thread_window/ThreadWindow.cpp @@ -14,7 +14,9 @@ #include -//#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 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); +} diff --git a/src/apps/debuganalyzer/gui/thread_window/ThreadWindow.h b/src/apps/debuganalyzer/gui/thread_window/ThreadWindow.h index 03e8b0df69..752b1acbb7 100644 --- a/src/apps/debuganalyzer/gui/thread_window/ThreadWindow.h +++ b/src/apps/debuganalyzer/gui/thread_window/ThreadWindow.h @@ -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; }; diff --git a/src/apps/debuganalyzer/gui/thread_window/WaitObjectsPage.cpp b/src/apps/debuganalyzer/gui/thread_window/WaitObjectsPage.cpp index ff701cfdf7..6ac17c12d9 100644 --- a/src/apps/debuganalyzer/gui/thread_window/WaitObjectsPage.cpp +++ b/src/apps/debuganalyzer/gui/thread_window/WaitObjectsPage.cpp @@ -11,6 +11,8 @@ #include +#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 objectNodes; - GroupNode(Model::ThreadWaitObjectGroup* group) + GroupNode(ThreadModel::WaitObjectGroup* group) : group(group) { - BObjectList 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 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! } diff --git a/src/apps/debuganalyzer/gui/thread_window/WaitObjectsPage.h b/src/apps/debuganalyzer/gui/thread_window/WaitObjectsPage.h index fcb8bb8890..b89048a0f4 100644 --- a/src/apps/debuganalyzer/gui/thread_window/WaitObjectsPage.h +++ b/src/apps/debuganalyzer/gui/thread_window/WaitObjectsPage.h @@ -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; }; diff --git a/src/apps/debuganalyzer/model/Jamfile b/src/apps/debuganalyzer/model/Jamfile index d50ee887e3..dbba72ba0f 100644 --- a/src/apps/debuganalyzer/model/Jamfile +++ b/src/apps/debuganalyzer/model/Jamfile @@ -9,4 +9,5 @@ UseHeaders $(HAIKU_DEBUG_ANALYZER_HEADERS) ; MergeObject DebugAnalyzer_model.o : Model.cpp + ThreadModel.cpp ; diff --git a/src/apps/debuganalyzer/model/ThreadModel.cpp b/src/apps/debuganalyzer/model/ThreadModel.cpp new file mode 100644 index 0000000000..423cab200c --- /dev/null +++ b/src/apps/debuganalyzer/model/ThreadModel.cpp @@ -0,0 +1,78 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "ThreadModel.h" + +#include + + +// #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& 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; +} diff --git a/src/apps/debuganalyzer/model/ThreadModel.h b/src/apps/debuganalyzer/model/ThreadModel.h new file mode 100644 index 0000000000..b0fb306cb9 --- /dev/null +++ b/src/apps/debuganalyzer/model/ThreadModel.h @@ -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 + +#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& + waitObjects, + int32 start, int32 end); + inline int32 CountWaitObjectGroups() const; + inline WaitObjectGroup* WaitObjectGroupAt(int32 index) const; + +private: + typedef BObjectList 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 diff --git a/src/apps/debuganalyzer/model_loader/Jamfile b/src/apps/debuganalyzer/model_loader/Jamfile index 29ec0115a3..09a8fdec6b 100644 --- a/src/apps/debuganalyzer/model_loader/Jamfile +++ b/src/apps/debuganalyzer/model_loader/Jamfile @@ -10,4 +10,5 @@ MergeObject DebugAnalyzer_model_loader.o : AbstractModelLoader.cpp ModelLoader.cpp + ThreadModelLoader.cpp ; diff --git a/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp b/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp new file mode 100644 index 0000000000..5fa79e4548 --- /dev/null +++ b/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp @@ -0,0 +1,130 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "ThreadModelLoader.h" + +#include + +#include + +#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 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 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; +} diff --git a/src/apps/debuganalyzer/model_loader/ThreadModelLoader.h b/src/apps/debuganalyzer/model_loader/ThreadModelLoader.h new file mode 100644 index 0000000000..e1787d37f9 --- /dev/null +++ b/src/apps/debuganalyzer/model_loader/ThreadModelLoader.h @@ -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