Pulled base class AbstractModelLoader out of ModelLoader.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30427 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-04-26 13:59:38 +00:00
parent 5bfd73fb71
commit 64d5660eab
6 changed files with 233 additions and 105 deletions
@@ -62,7 +62,8 @@ MainWindow::MainWindow(DataSource* dataSource)
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
delete fModelLoader; if (fModelLoader != NULL)
fModelLoader->Delete();
if (fModel != NULL) if (fModel != NULL)
fModel->RemoveReference(); fModel->RemoveReference();
@@ -79,7 +80,7 @@ MainWindow::MessageReceived(BMessage* message)
{ {
printf("MSG_MODEL_LOADED_SUCCESSFULLY\n"); printf("MSG_MODEL_LOADED_SUCCESSFULLY\n");
Model* model = fModelLoader->DetachModel(); Model* model = fModelLoader->DetachModel();
delete fModelLoader; fModelLoader->Delete();
fModelLoader = NULL; fModelLoader = NULL;
_SetModel(model); _SetModel(model);
model->RemoveReference(); model->RemoveReference();
@@ -90,7 +91,7 @@ printf("MSG_MODEL_LOADED_SUCCESSFULLY\n");
case MSG_MODEL_LOADED_ABORTED: case MSG_MODEL_LOADED_ABORTED:
{ {
printf("MSG_MODEL_LOADED_FAILED/MSG_MODEL_LOADED_ABORTED\n"); printf("MSG_MODEL_LOADED_FAILED/MSG_MODEL_LOADED_ABORTED\n");
delete fModelLoader; fModelLoader->Delete();
fModelLoader = NULL; fModelLoader = NULL;
// TODO: User feedback (in failed case)! // TODO: User feedback (in failed case)!
break; break;
@@ -128,7 +129,7 @@ MainWindow::Show()
status_t error = fModelLoader->StartLoading(); status_t error = fModelLoader->StartLoading();
if (error != B_OK) { if (error != B_OK) {
delete fModelLoader; fModelLoader->Delete();
fModelLoader = NULL; fModelLoader = NULL;
// TODO: User feedback! // TODO: User feedback!
} }
@@ -0,0 +1,150 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "AbstractModelLoader.h"
#include <AutoLocker.h>
#include "MessageCodes.h"
AbstractModelLoader::AbstractModelLoader(const BMessenger& target,
void* targetCookie)
:
fLock("main model loader"),
fTarget(target),
fTargetCookie(targetCookie),
fLoaderThread(-1),
fLoading(false),
fAborted(false)
{
}
AbstractModelLoader::~AbstractModelLoader()
{
}
status_t
AbstractModelLoader::StartLoading()
{
// check initialization
status_t error = fLock.InitCheck();
if (error != B_OK)
return error;
AutoLocker<BLocker> locker(fLock);
if (fLoading)
return B_BAD_VALUE;
// prepare for loading
error = PrepareForLoading();
if (error != B_OK)
return error;
// spawn the loader thread
fLoaderThread = spawn_thread(&_LoaderEntry, "model loader",
B_NORMAL_PRIORITY, this);
if (fLoaderThread < 0)
return fLoaderThread;
fLoading = true;
fAborted = false;
resume_thread(fLoaderThread);
return B_OK;
}
void
AbstractModelLoader::Abort(bool wait)
{
AutoLocker<BLocker> locker(fLock);
if (fLoaderThread < 0)
return;
thread_id thread = fLoaderThread;
if (fLoading)
fAborted = true;
locker.Unlock();
if (wait)
wait_for_thread(thread, NULL);
}
void
AbstractModelLoader::Delete()
{
Abort(true);
delete this;
}
/*! Called from StartLoading() with the lock held.
*/
status_t
AbstractModelLoader::PrepareForLoading()
{
return B_OK;
}
status_t
AbstractModelLoader::Load()
{
return B_OK;
}
/*! Called after loading Load() is done with the lock held.
*/
void
AbstractModelLoader::FinishLoading(bool success)
{
}
void
AbstractModelLoader::NotifyTarget(bool success)
{
BMessage message(success
? MSG_MODEL_LOADED_SUCCESSFULLY
: fAborted ? MSG_MODEL_LOADED_ABORTED : MSG_MODEL_LOADED_FAILED);
message.AddPointer("loader", this);
message.AddPointer("targetCookie", fTargetCookie);
fTarget.SendMessage(&message);
}
/*static*/ status_t
AbstractModelLoader::_LoaderEntry(void* data)
{
return ((AbstractModelLoader*)data)->_Loader();
}
status_t
AbstractModelLoader::_Loader()
{
bool success = Load() == B_OK;
// clean up and notify the target
AutoLocker<BLocker> locker(fLock);
FinishLoading(success);
NotifyTarget(success);
fLoading = false;
return B_OK;
}
@@ -0,0 +1,46 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef ABSTRACT_MODEL_LOADER_H
#define ABSTRACT_MODEL_LOADER_H
#include <Locker.h>
#include <Messenger.h>
class AbstractModelLoader {
public:
AbstractModelLoader(const BMessenger& target,
void* targetCookie);
protected:
~AbstractModelLoader();
public:
virtual status_t StartLoading();
virtual void Abort(bool wait);
virtual void Delete();
protected:
virtual status_t PrepareForLoading();
virtual status_t Load();
virtual void FinishLoading(bool success);
void NotifyTarget(bool success);
private:
static status_t _LoaderEntry(void* data);
status_t _Loader();
protected:
BLocker fLock;
BMessenger fTarget;
void* fTargetCookie;
thread_id fLoaderThread;
bool fLoading;
bool fAborted;
};
#endif // ABSTRACT_MODEL_LOADER_H
@@ -8,5 +8,6 @@ UseHeaders $(HAIKU_DEBUG_ANALYZER_HEADERS) ;
MergeObject DebugAnalyzer_model_loader.o MergeObject DebugAnalyzer_model_loader.o
: :
AbstractModelLoader.cpp
ModelLoader.cpp ModelLoader.cpp
; ;
@@ -70,80 +70,20 @@ ModelLoader::_UpdateLastEventTime(bigtime_t time)
ModelLoader::ModelLoader(DataSource* dataSource, ModelLoader::ModelLoader(DataSource* dataSource,
const BMessenger& target, void* targetCookie) const BMessenger& target, void* targetCookie)
: :
fLock("main model loader"), AbstractModelLoader(target, targetCookie),
fModel(NULL), fModel(NULL),
fDataSource(dataSource), fDataSource(dataSource)
fTarget(target),
fTargetCookie(targetCookie),
fLoaderThread(-1),
fLoading(false),
fAborted(false)
{ {
} }
ModelLoader::~ModelLoader() ModelLoader::~ModelLoader()
{ {
Abort(true);
delete fDataSource; delete fDataSource;
delete fModel; delete fModel;
} }
status_t
ModelLoader::StartLoading()
{
// check initialization
status_t error = fLock.InitCheck();
if (error != B_OK)
return error;
AutoLocker<BLocker> locker(fLock);
if (fModel != NULL || fLoading || fDataSource == NULL)
return B_BAD_VALUE;
// init the hash tables
error = fThreads.Init();
if (error != B_OK)
return error;
// spawn the loader thread
fLoaderThread = spawn_thread(&_LoaderEntry, "main model loader",
B_NORMAL_PRIORITY, this);
if (fLoaderThread < 0)
return fLoaderThread;
fLoading = true;
fAborted = false;
resume_thread(fLoaderThread);
return B_OK;
}
void
ModelLoader::Abort(bool wait)
{
AutoLocker<BLocker> locker(fLock);
if (fLoaderThread < 0)
return;
thread_id thread = fLoaderThread;
if (fLoading)
fAborted = true;
locker.Unlock();
if (wait)
wait_for_thread(thread, NULL);
}
Model* Model*
ModelLoader::DetachModel() ModelLoader::DetachModel()
{ {
@@ -159,26 +99,35 @@ ModelLoader::DetachModel()
} }
/*static*/ status_t status_t
ModelLoader::_LoaderEntry(void* data) ModelLoader::PrepareForLoading()
{ {
return ((ModelLoader*)data)->_Loader(); if (fModel != NULL || fDataSource == NULL)
return B_BAD_VALUE;
// init the hash tables
status_t error = fThreads.Init();
if (error != B_OK)
return error;
return B_OK;
} }
status_t status_t
ModelLoader::_Loader() ModelLoader::Load()
{ {
status_t error;
try { try {
error = _Load(); return _Load();
} catch(...) { } catch(...) {
error = B_ERROR; return B_ERROR;
} }
}
// clean up and notify the target
AutoLocker<BLocker> locker(fLock);
void
ModelLoader::FinishLoading(bool success)
{
ThreadInfo* threadInfo = fThreads.Clear(true); ThreadInfo* threadInfo = fThreads.Clear(true);
while (threadInfo != NULL) { while (threadInfo != NULL) {
ThreadInfo* nextInfo = threadInfo->fNext; ThreadInfo* nextInfo = threadInfo->fNext;
@@ -186,24 +135,10 @@ ModelLoader::_Loader()
threadInfo = nextInfo; threadInfo = nextInfo;
} }
BMessage message; if (!success) {
if (error == B_OK) {
message.what = MSG_MODEL_LOADED_SUCCESSFULLY;
} else {
delete fModel; delete fModel;
fModel = NULL; fModel = NULL;
message.what = fAborted
? MSG_MODEL_LOADED_ABORTED : MSG_MODEL_LOADED_FAILED;
} }
message.AddPointer("loader", this);
message.AddPointer("targetCookie", fTargetCookie);
fTarget.SendMessage(&message);
fLoading = false;
return B_OK;
} }
@@ -5,11 +5,9 @@
#ifndef MAIN_MODEL_LOADER_H #ifndef MAIN_MODEL_LOADER_H
#define MAIN_MODEL_LOADER_H #define MAIN_MODEL_LOADER_H
#include <Locker.h>
#include <Messenger.h>
#include <util/OpenHashTable.h> #include <util/OpenHashTable.h>
#include "AbstractModelLoader.h"
#include "Model.h" #include "Model.h"
@@ -19,18 +17,23 @@ class DataSource;
struct system_profiler_thread_added; struct system_profiler_thread_added;
class ModelLoader { class ModelLoader : public AbstractModelLoader {
public: public:
ModelLoader(DataSource* dataSource, ModelLoader(DataSource* dataSource,
const BMessenger& target, const BMessenger& target,
void* targetCookie); void* targetCookie);
protected:
~ModelLoader(); ~ModelLoader();
status_t StartLoading(); public:
void Abort(bool wait);
Model* DetachModel(); Model* DetachModel();
protected:
virtual status_t PrepareForLoading();
virtual status_t Load();
virtual void FinishLoading(bool success);
private: private:
enum ScheduleState { enum ScheduleState {
RUNNING, RUNNING,
@@ -78,8 +81,6 @@ private:
thread_removed_from_run_queue; thread_removed_from_run_queue;
private: private:
static status_t _LoaderEntry(void* data);
status_t _Loader();
status_t _Load(); status_t _Load();
status_t _ReadDebugEvents(void** _eventData, status_t _ReadDebugEvents(void** _eventData,
size_t* _size); size_t* _size);
@@ -112,14 +113,8 @@ private:
uint32 type, addr_t object); uint32 type, addr_t object);
private: private:
BLocker fLock;
Model* fModel; Model* fModel;
DataSource* fDataSource; DataSource* fDataSource;
BMessenger fTarget;
void* fTargetCookie;
thread_id fLoaderThread;
bool fLoading;
bool fAborted;
bigtime_t fBaseTime; bigtime_t fBaseTime;
bigtime_t fLastEventTime; bigtime_t fLastEventTime;
ThreadTable fThreads; ThreadTable fThreads;