Commit 4c017151 authored by schultezub's avatar schultezub
Browse files

* fixed memory leaks

 * fixed kisscl::CommandQueue destructor
 * documented OpenGLJobProcessor scheduling strategy

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@254 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 61d44af5
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#ifndef TUMVISAPPLICATION_H__ #ifndef TUMVISAPPLICATION_H__
#define TUMVISAPPLICATION_H__ #define TUMVISAPPLICATION_H__
//#include <vld.h> // Uncomment this for using Visual Leak Detector
#include "sigslot/sigslot.h" #include "sigslot/sigslot.h"
#include <QApplication> #include <QApplication>
#include <utility> #include <utility>
......
...@@ -41,7 +41,16 @@ namespace TUMVis { ...@@ -41,7 +41,16 @@ namespace TUMVis {
} }
OpenGLJobProcessor::~OpenGLJobProcessor() { OpenGLJobProcessor::~OpenGLJobProcessor() {
// delete all per-context job queues and unfinished jobs
for (tbb::concurrent_vector<tgt::GLCanvas*>::const_iterator it = _contexts.begin(); it != _contexts.end(); ++it) {
tbb::concurrent_hash_map<tgt::GLCanvas*, PerContextJobQueue*>::const_accessor a;
if (_contextQueueMap.find(a, *it)) {
delete a->second;
}
}
_contextQueueMap.clear();
_contexts.clear();
} }
void OpenGLJobProcessor::stop() { void OpenGLJobProcessor::stop() {
...@@ -57,6 +66,7 @@ namespace TUMVis { ...@@ -57,6 +66,7 @@ namespace TUMVis {
while (! _stopExecution) { while (! _stopExecution) {
// this is a simple round-robing scheduling between all contexts: // this is a simple round-robing scheduling between all contexts:
bool hadWork = false; bool hadWork = false;
// TODO: consider only non-empty context queues here
clock_t maxTimePerContext = 30 / _contexts.size(); clock_t maxTimePerContext = 30 / _contexts.size();
for (size_t i = 0; i < _contexts.size(); ++i) { for (size_t i = 0; i < _contexts.size(); ++i) {
......
...@@ -48,7 +48,23 @@ namespace tgt { ...@@ -48,7 +48,23 @@ namespace tgt {
namespace TUMVis { namespace TUMVis {
/** /**
* \todo Explain scheduling technique. * Singleton class for managing and executing work items (jobs) that need an active OpenGL context.
* After an OpenGL context has been registered you can enqueue jobs that are to be executed within that
* context to the job queue. Enqueued jobs are executed asynchroniously using a specific scheduling
* strategy, depending on the given JobType:
*
* OpenGLJobProcessor implements a round-robin scheduling strategy for the registered OpenGL contexts,
* meaning that each context gets roughly the same computing time. Thereby, it tries to maintain an update
* frequency of 30fps for each context.
* The jobs for each contexts are scheduled using the following technique: As mentioned above, each context
* has a time slot of \a n milliseconds. At first, as much serial jobs are executed as possible until their
* queue is empty or or the time is up. Then, one low priority job is executed. Finally, the PaintJob is
* executed (if existant) before switching to the next context.
*
* This class implements the Runnable interface, hence, runs in its own thread. Furthermore, it uses
* conditional wait, when there are currently no jobs to process.
*
* This class is to be considered as thread-safe.
*/ */
class OpenGLJobProcessor : public tgt::Singleton<OpenGLJobProcessor>, public Runnable, public sigslot::has_slots<> { class OpenGLJobProcessor : public tgt::Singleton<OpenGLJobProcessor>, public Runnable, public sigslot::has_slots<> {
friend class tgt::Singleton<OpenGLJobProcessor>; friend class tgt::Singleton<OpenGLJobProcessor>;
...@@ -63,6 +79,9 @@ namespace TUMVis { ...@@ -63,6 +79,9 @@ namespace TUMVis {
LowPriorityJob ///< Low priority jobs have the lowest priority, can be executed at any time. The only guarantee is that thay won't starve. LowPriorityJob ///< Low priority jobs have the lowest priority, can be executed at any time. The only guarantee is that thay won't starve.
}; };
/**
* Destructor, deletes all unfinished jobs.
*/
virtual ~OpenGLJobProcessor(); virtual ~OpenGLJobProcessor();
...@@ -102,7 +121,20 @@ namespace TUMVis { ...@@ -102,7 +121,20 @@ namespace TUMVis {
*/ */
PerContextJobQueue() PerContextJobQueue()
: _paintJob(0) : _paintJob(0)
{ {}
/**
* Destructor, deletes all enqueued jobs.
*/
~PerContextJobQueue() {
if (_paintJob != 0)
delete _paintJob;
AbstractJob* jobToDelete = 0;
while (_serialJobs.try_pop(jobToDelete))
delete jobToDelete;
while (_lowPriorityJobs.try_pop(jobToDelete))
delete jobToDelete;
} }
AbstractJob* _paintJob; ///< PaintJob of the context AbstractJob* _paintJob; ///< PaintJob of the context
......
...@@ -33,6 +33,11 @@ namespace kisscl { ...@@ -33,6 +33,11 @@ namespace kisscl {
} }
CLRuntime::~CLRuntime() { CLRuntime::~CLRuntime() {
// delete all command queues
for (std::map< std::pair<Context*, Device*>, CommandQueue*>::iterator it = _commandQueues.begin(); it != _commandQueues.end(); ++it)
delete it->second;
// delete all platforms and with it all devices
for (std::vector<Platform*>::iterator it = _platforms.begin(); it != _platforms.end(); ++it) for (std::vector<Platform*>::iterator it = _platforms.begin(); it != _platforms.end(); ++it)
delete *it; delete *it;
} }
......
...@@ -63,8 +63,7 @@ namespace kisscl { ...@@ -63,8 +63,7 @@ namespace kisscl {
// = getters and setters ========================================================================== // = getters and setters ==========================================================================
CommandQueue::~CommandQueue() { CommandQueue::~CommandQueue() {
if (_id != 0)
clReleaseCommandQueue(_id);
} }
const Context* CommandQueue::getContext() const { const Context* CommandQueue::getContext() const {
......
...@@ -99,6 +99,7 @@ namespace TUMVis { ...@@ -99,6 +99,7 @@ namespace TUMVis {
void CLRaycaster::deinit() { void CLRaycaster::deinit() {
CLRtm.dispose(_clProgram); CLRtm.dispose(_clProgram);
delete _clContext;
VisualizationProcessor::deinit(); VisualizationProcessor::deinit();
} }
......
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