Starting from 2021-07-01, all LRZ GitLab users will be required to explicitly accept the GitLab Terms of Service. Please see the detailed information at https://doku.lrz.de/display/PUBLIC/GitLab and make sure that your projects conform to the requirements.

Commit a503bd11 authored by schultezub's avatar schultezub
Browse files

PipelineEvaluator implements Runnable

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@197 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 4609c893
......@@ -18,11 +18,6 @@ SliceVis* sliceVis = 0;
TumVisPainter* painter = 0;
PipelineEvaluator* pe;
void startEvaluator() {
pe = new PipelineEvaluator(sliceVis);
pe->startEvaluation();
}
void startPainter() {
painter->run();
}
......@@ -78,15 +73,15 @@ int main(int argc, char** argv) {
// disconnect OpenGL context from this thread so that the other threads can acquire an OpenGL context.
CtxtMgr.releaseCurrentContext();
std::thread evaluatorThread(&startEvaluator);
pe = new PipelineEvaluator(sliceVis);
pe->start();
std::thread painterThread(&startPainter);
app->run();
painter->stop();
pe->stopEvaluation();
pe->stop();
evaluatorThread.join();
painterThread.join();
sliceVis->deinit();
......
#include "pipelineevaluator.h"
#include "tgt/qt/qtcontextmanager.h"
namespace TUMVis {
const std::string PipelineEvaluator::loggerCat_ = "TUMVis.core.pipeline.PipelineEvaluator";
PipelineEvaluator::PipelineEvaluator(AbstractPipeline* pipeline)
: _pipeline(pipeline)
, _evaluationThread()
: Runnable()
, _pipeline(pipeline)
{
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;
void PipelineEvaluator::run() {
std::unique_lock<tbb::mutex> lock(_pipeline->_evaluationMutex);
while (_evaluatePipeline) {
while (! _stopExecution) {
_pipeline->execute();
while (_evaluatePipeline && _pipeline->getInvalidationLevel().isValid())
while (!_stopExecution && _pipeline->getInvalidationLevel().isValid())
_evaluationCondition.wait(lock);
}
// release OpenGL context, so that other threads can access it
CtxtMgr.releaseCurrentContext();
}
void PipelineEvaluator::stopEvaluation() {
_evaluatePipeline = false;
void PipelineEvaluator::stop() {
_stopExecution = true;
_evaluationCondition.notify_all();
Runnable::stop();
}
void PipelineEvaluator::OnPipelineInvalidated() {
if (_evaluatePipeline)
if (!_stopExecution)
_evaluationCondition.notify_all();
}
......
......@@ -3,6 +3,7 @@
#include "sigslot/sigslot.h"
#include "core/pipeline/abstractpipeline.h"
#include "core/tools/runnable.h"
#include "tbb/include/tbb/compat/thread"
#include "tbb/include/tbb/compat/condition_variable"
#include "tbb/include/tbb/atomic.h"
......@@ -10,31 +11,41 @@
namespace TUMVis {
/**
* The PipelineEvaluator
* The PipelineEvaluator evaluates its pipeline in its own thread.
* Evaluation is implemented using condidional wait - hence the pipeline is only evaluated when
* \a pipeline emits the s_PipelineInvalidated signal.
* \sa Runnable
*/
class PipelineEvaluator : public sigslot::has_slots<> {
class PipelineEvaluator : public Runnable, public sigslot::has_slots<> {
public:
/**
* Creates a new PipelineEvaluator for the given pipeline \a pipeline.
* \param pipeline Pipeline to evaluate
*/
PipelineEvaluator(AbstractPipeline* pipeline);
/**
* Destructor, stops and waits for the evaluation thread if it's still running.
*/
~PipelineEvaluator();
void startEvaluation();
void stopEvaluation();
void evaluate();
/// \see Runnable::stop
void stop();
/**
* Performs the pipeline evaluation using conditional wait.
* \sa Runnable::run
*/
void run();
/**
* Slot for notifications when the pipeline was invalidated.
*/
void OnPipelineInvalidated();
protected:
AbstractPipeline* _pipeline;
tbb::atomic<bool> _evaluatePipeline;
std::thread _evaluationThread;
std::condition_variable _evaluationCondition;
static const std::string loggerCat_;
AbstractPipeline* _pipeline; ///< Pipeline to evaluate
std::condition_variable _evaluationCondition; ///< conditional wait condition
};
}
......
#include "runnable.h"
namespace TUMVis {
namespace {
void invokeThread(Runnable* r) {
r->run();
}
}
Runnable::Runnable()
: _stopExecution()
, _thread()
{
_stopExecution = false;
}
Runnable::~Runnable() {
stop();
}
void Runnable::stop() {
_stopExecution = true;
try {
_thread.join();
}
catch(std::exception& e) {
LERRORC("TUMVis.core.tools.Runnable", "Caught exception during _thread.join: " << e.what());
}
}
void Runnable::start() {
_thread = std::thread(&invokeThread, this);
}
}
......@@ -8,41 +8,48 @@
namespace TUMVis {
/**
* Abstract base class for objects that shall run in a separate thread.
* Runnable object manage their own thread, which is created when calling start(). The new Thread starts
* in the run() method which has to be overwritten in subclasses. Calling stop() sets _stopExecution to true
* and waits for the thread to finish. Hence, you should test for _stopExecution in your run() method.
*/
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);
}
/**
* Creates a new Runnable object
*/
Runnable();
/**
* Destructor, stops and waits the thread if the thread is still running.
*/
virtual ~Runnable();
/**
* Creates the new thread evaluating the run() method.
* \sa Runnable::run
*/
virtual void start();
/**
* Sets the _stopExecution flag and waits for the thread to finish.
*/
virtual void stop();
/**
* Entrance point for the new thread. To be overwritten in subclasses.
*/
virtual void run() = 0;
protected:
virtual void run() = 0;
tbb::atomic<bool> _stopExecution;
tbb::atomic<bool> _stopExecution; ///< Flag whether the thread should stop
private:
Runnable(Runnable const&) = delete;
Runnable& operator =(Runnable const&) = delete;
/// Runnables are not copyable
Runnable(Runnable const&);
/// Runnables are not copyable
Runnable& operator =(Runnable const&);
std::thread _thread;
std::thread _thread; ///< Thread of the Runnable
};
}
......
......@@ -28,7 +28,7 @@ SET(TGT_SOURCES
assert.cpp
bounds.cpp
bspline.cpp
buffer.cpp
# buffer.cpp
camera.cpp
catmullromspline.cpp
curve.cpp
......
......@@ -39,7 +39,9 @@ namespace tgt {
_renderCondition.wait(&CtxtMgr.getGlMutex());
qtContext->acquire();
}
//exit();
// release OpenGL context, so that other threads can access it
CtxtMgr.releaseCurrentContext();
}
void QtThreadedPainter::setCanvas(GLCanvas* canvas) {
......
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