Commit 4609c893 authored by schultezub's avatar schultezub
Browse files

* started implementing proper deinitialization of everything

 * added Runnable interface
 * started letting PipelineEvaluator manage its thread itself
 * documentation

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@196 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 1302ca97
......@@ -12,8 +12,6 @@
#include "core/pipeline/pipelineevaluator.h"
#include "modules/pipelines/slicevis.h"
#include <functional>
using namespace TUMVis;
SliceVis* sliceVis = 0;
......@@ -44,7 +42,6 @@ int main(int argc, char** argv) {
tbb::task_scheduler_init init;
renderCanvas->getContext()->acquire();
app->addCanvas(renderCanvas);
//app->addCanvas(sliceVisCanvas);
app->init();
LogMgr.getConsoleLog()->addCat("", true);
LGL_ERROR;
......@@ -92,6 +89,12 @@ int main(int argc, char** argv) {
evaluatorThread.join();
painterThread.join();
sliceVis->deinit();
painter->deinit();
tgt::deinitGL();
tgt::QtContextManager::deinit();
tgt::deinit();
delete painter;
delete sliceVis;
delete app;
......
......@@ -89,7 +89,6 @@ namespace TUMVis {
void TumVisPainter::sizeChanged(const tgt::ivec2& size) {
_pipeline->setRenderTargetSize(size);
_renderCondition.wakeAll();
}
void TumVisPainter::init() {
......@@ -102,6 +101,10 @@ namespace TUMVis {
}
}
void TumVisPainter::deinit() {
ShdrMgr.dispose(_copyShader);
}
void TumVisPainter::setPipeline(VisualizationPipeline* pipeline) {
tgtAssert(pipeline != 0, "The given pipeline must not be 0.");
if (_pipeline != 0) {
......
......@@ -26,6 +26,7 @@ namespace TUMVis {
virtual void paint();
virtual void sizeChanged(const tgt::ivec2& size);
virtual void init();
virtual void deinit();
void setPipeline(VisualizationPipeline* pipeline);
void onPipelineInvalidated();
......
......@@ -27,6 +27,18 @@ namespace TUMVis {
}
}
void AbstractPipeline::deinit() {
// deinitialize all processors:
for (std::vector<AbstractProcessor*>::iterator it = _processors.begin(); it != _processors.end(); ++it) {
try {
(*it)->deinit();
}
catch (tgt::Exception& e) {
LERROR("Caught Exception during deinitialization of processor: " << e.what());
}
}
}
void AbstractPipeline::onNotify(const ProcessorObserverArgs& poa) {
_invalidationLevel.setLevel(InvalidationLevel::INVALID_RESULT);
s_PipelineInvalidated();
......@@ -42,10 +54,6 @@ namespace TUMVis {
processor.unlockProperties();
}
tbb::mutex& AbstractPipeline::getEvaluationMutex() {
return _evaluationMutex;
}
InvalidationLevel& AbstractPipeline::getInvalidationLevel() {
return _invalidationLevel;
}
......
......@@ -15,12 +15,14 @@
#include <vector>
namespace TUMVis {
class PipelineEvaluator;
/**
* Abstract base class for TUMVis Pipelines.
*
*/
class AbstractPipeline : public GenericObserver<ProcessorObserverArgs> {
friend class PipelineEvaluator;
public:
/**
* Creates a AbstractPipeline.
......@@ -34,12 +36,19 @@ namespace TUMVis {
/**
* Initializes the OpenGL context of the pipeline and its processors.
* Initializes this pipeline and all of its processors.
* Everything that requires a valid OpenGL context or is otherwise expensive gets in here.
*
* \note When overwriting this method, make sure to call the base class version first.
*/
virtual void init();
/**
* Deinitializes this pipeline and all of its processors.
* \note When overwriting this method, make sure to call the base class version first.
*/
virtual void deinit();
/**
* Execute this pipeline.
**/
......@@ -65,8 +74,6 @@ namespace TUMVis {
*/
virtual void onNotify(const ProcessorObserverArgs& poa);
tbb::mutex& getEvaluationMutex();
InvalidationLevel& getInvalidationLevel();
......@@ -85,7 +92,7 @@ namespace TUMVis {
InvalidationLevel _invalidationLevel; ///< current invalidation level
tbb::spin_mutex _localMutex; ///< mutex for altering local members
tbb::mutex _evaluationMutex; ///< mutex for the evaluation of this pipeline
tbb::mutex _evaluationMutex; ///< mutex for the evaluation of this pipeline
static const std::string loggerCat_;
};
......
......@@ -34,9 +34,12 @@ namespace TUMVis {
}
void AbstractProcessor::init() {
}
void AbstractProcessor::deinit() {
}
void AbstractProcessor::lockProperties() {
_properties.lockAllProperties();
}
......
......@@ -69,10 +69,18 @@ namespace TUMVis {
/**
* Initializes the OpenGL context of the processor.
* Initializes the processor.
* Everything that requires a valid OpenGL context or is otherwise expensive gets in here.
*
* \note When overwriting this method, make sure to call the base class version first.
*/
virtual void init();
/**
* Deinitializes this processors.
* \note When overwriting this method, make sure to call the base class version first.
*/
virtual void deinit();
/**
* Execute this processor.
......
......@@ -6,19 +6,21 @@ namespace TUMVis {
PipelineEvaluator::PipelineEvaluator(AbstractPipeline* pipeline)
: _pipeline(pipeline)
, _evaluatePipeline(false)
, _evaluationThread()
{
tgtAssert(pipeline != 0, "Pipeline must not be 0.");
_evaluatePipeline = false;
pipeline->s_PipelineInvalidated.connect(this, &PipelineEvaluator::OnPipelineInvalidated);
}
PipelineEvaluator::~PipelineEvaluator() {
_pipeline->s_PipelineInvalidated.disconnect(this);
}
void PipelineEvaluator::startEvaluation() {
_evaluatePipeline = true;
std::unique_lock<tbb::mutex> lock(_pipeline->getEvaluationMutex());
std::unique_lock<tbb::mutex> lock(_pipeline->_evaluationMutex);
while (_evaluatePipeline) {
_pipeline->execute();
......
......@@ -3,12 +3,14 @@
#include "sigslot/sigslot.h"
#include "core/pipeline/abstractpipeline.h"
#include "tbb/include/tbb/compat/thread"
#include "tbb/include/tbb/compat/condition_variable"
#include "tbb/include/tbb/atomic.h"
namespace TUMVis {
/**
*
* The PipelineEvaluator
*/
class PipelineEvaluator : public sigslot::has_slots<> {
public:
......@@ -18,16 +20,18 @@ namespace TUMVis {
void startEvaluation();
void stopEvaluation();
void evaluate();
void OnPipelineInvalidated();
protected:
AbstractPipeline* _pipeline;
bool _evaluatePipeline;
tbb::atomic<bool> _evaluatePipeline;
std::thread _evaluationThread;
std::condition_variable _evaluationCondition;
static const std::string loggerCat_;
......
......@@ -45,6 +45,11 @@ namespace TUMVis {
AbstractPipeline::init();
}
void VisualizationPipeline::deinit() {
tgt::GLContextScopedLock lock(_canvas->getContext());
AbstractPipeline::deinit();
}
const tgt::ivec2& VisualizationPipeline::getRenderTargetSize() const {
return _renderTargetSize.getValue();
}
......@@ -66,7 +71,7 @@ namespace TUMVis {
void VisualizationPipeline::lockGLContextAndExecuteProcessor(AbstractProcessor& processor) {
tgt::GLContextScopedLock lock(_canvas->getContext());
executeProcessor(processor);
glFlush();
glFlush(); // TODO: is glFlush enough or do we need a glFinish here?
}
}
......@@ -39,6 +39,12 @@ namespace TUMVis {
*/
virtual void init();
/**
* Deinitializes this pipeline and all of its processors.
* \note When overwriting this method, make sure to call the base class version first.
*/
virtual void deinit();
/**
* Execute this pipeline.
**/
......@@ -86,7 +92,7 @@ namespace TUMVis {
*/
void onDataContainerDataAdded(const std::string& name, const DataHandle* dh);
/// Signal emitted when the pipeline's render target has changed
sigslot::signal0<> s_renderTargetChanged;
protected:
......
......@@ -4,9 +4,10 @@ namespace TUMVis {
VisualizationProcessor::VisualizationProcessor(GenericProperty<tgt::ivec2>& canvasSize)
: AbstractProcessor()
, _canvasSize("canvasSize", "Canvas Size", canvasSize.getValue())
, _renderTargetSize("canvasSize", "Canvas Size", canvasSize.getValue())
{
canvasSize.addSharedProperty(&_canvasSize);
canvasSize.addSharedProperty(&_renderTargetSize);
_renderTargetSize.addObserver(this);
}
VisualizationProcessor::~VisualizationProcessor() {
......
......@@ -9,25 +9,25 @@
namespace TUMVis {
/**
* Abstract base class for TUMVis Processors.
* A processor implements a specific task, which it performs on the DataCollection passed
* during process(). Properties provide a transparent layer for adjusting the processor's
* behaviour.
* Once a processor has finished it sets it should set its invalidation level to valid. As
* soon as one of its properties changes, the processor will be notified and possibliy
* change its invalidation level. Observing pipelines will be notified of this and can
* and have to decide which part of the pipeline has to be re-evaluated wrt. the processor's
* invalidation level.
* Specialization of AbstractProcessor for visualization purposes.
* VisualizationProcessors are required to be called by a VisualizationPipeline which ensure
* to provide a valid OpenGL context when calling the processor's process() method. Hence, a
* VisualizationProcessor is allowed/capable of performing OpenGl operations.
* For determining the canvas/viewport size, a VisualizationProcessor gets a reference to the
* parent pipeline's render target size property during instantiation.
*
* \sa AbstractPipeline
* \sa VisualizationPipeline
*/
class VisualizationProcessor : public AbstractProcessor {
public:
/**
* Creates a VisualizationProcessor.
* \note The render target size property of this VisualizationProcessor will automatically
* be assigned as shared property of the given \a renderTargetSize property.
* \param renderTargetSize Reference to the parent pipeline's render target size property.
*/
VisualizationProcessor(GenericProperty<tgt::ivec2>& canvasSize);
VisualizationProcessor(GenericProperty<tgt::ivec2>& renderTargetSize);
/**
* Virtual Destructor
......@@ -36,7 +36,7 @@ namespace TUMVis {
protected:
GenericProperty<tgt::ivec2> _canvasSize; ///< Viewport size of target canvas
GenericProperty<tgt::ivec2> _renderTargetSize; ///< Viewport size of target canvas
};
}
......
#ifndef RUNNABLE_H__
#define RUNNABLE_H__
#include "tgt/logmanager.h"
#include "tbb/include/tbb/compat/thread"
#include "tbb/include/tbb/atomic.h"
namespace TUMVis {
/**
* Abstract base class for objects that shall run in a separate thread.
*/
class Runnable {
public:
Runnable()
: _stopExecution()
, _thread()
{}
virtual ~Runnable() {
stop();
}
virtual void stop() {
_stopExecution = true;
try {
_thread.join();
}
catch(std::exception& e) {
LERRORC("TUMVis.core.tools.Runnable", "Caught exception during _thread.join: " << e.what());
}
}
void start() {
_thread = std::thread(&Runnable::run, *this);
}
protected:
virtual void run() = 0;
tbb::atomic<bool> _stopExecution;
private:
Runnable(Runnable const&) = delete;
Runnable& operator =(Runnable const&) = delete;
std::thread _thread;
};
}
#endif // RUNNABLE_H__
......@@ -67,7 +67,6 @@ public:
// override Qt events so that they don't interfere with the threading.
void resizeEvent(QResizeEvent *event) {
QWidget::resizeEvent(event);
sizeChanged(ivec2(event->size().width(), event->size().height()));
};
......
......@@ -31,6 +31,10 @@ namespace TUMVis {
_shader = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "modules/vis/sliceextractor.frag", "", false);
}
void SliceExtractor::deinit() {
ShdrMgr.dispose(_shader);
}
void SliceExtractor::process(DataContainer& data) {
const ImageDataLocal* img = data.getTypedData<ImageDataLocal>(_sourceImageID.getValue());
......@@ -40,7 +44,7 @@ namespace TUMVis {
const tgt::svec3& imgSize = img->getSize();
ImageDataLocal* slice = img->getSubImage(tgt::svec3(0, 0, _sliceNumber.getValue()), tgt::svec3(imgSize.x-1, imgSize.y-1, _sliceNumber.getValue()));
ImageDataGL* glData = ImageDataConverter::tryConvert<ImageDataGL>(slice);
ImageDataRenderTarget* rt = new ImageDataRenderTarget(tgt::svec3(_canvasSize.getValue(), 1));
ImageDataRenderTarget* rt = new ImageDataRenderTarget(tgt::svec3(_renderTargetSize.getValue(), 1));
_shader->activate();
tgt::TextureUnit inputUnit;
......
......@@ -26,9 +26,12 @@ namespace TUMVis {
**/
virtual ~SliceExtractor();
/// \see AbstractProcessor::init
virtual void init();
/// \see AbstractProcessor::deinit
virtual void deinit();
virtual void process(DataContainer& data);
GenericProperty<std::string> _sourceImageID; ///< image ID for input image
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment