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 0eb22d19 authored by schultezub's avatar schultezub
Browse files

* added Job interface

 * using concurrent_queue in JobPool


git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@250 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent d6f8fd1a
// ================================================================================================
//
// This file is part of the TUMVis Visualization Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
// Christian Schulte zu Berge (christian.szb@in.tum.de)
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#ifndef JOB_H__
#define JOB_H__
#include "sigslot/sigslot.h"
#include "tgt/assert.h"
namespace TUMVis {
/**
* Abstract base class for a job that can be executed.
*/
class AbstractJob {
public:
/**
* Pure virtual destructor.
*/
virtual ~AbstractJob() = 0 {};
/**
* Executes the job, to be overwritten by subclasses.
*/
virtual void execute() = 0;
};
/**
* Specific job, that is calling a member function pasing no argument.
*/
template<class T>
class CallMemberFuncJob {
public:
/**
* Creates an new job, that is calling \a callee on \a target pasing no argument.
* \param target Target object
* \param callee Member function to call
*/
CallMemberFuncJob(T* target, void (T::*callee)())
: _target(target)
, _callee(callee)
{
tgtAssert(_target != 0, "Target object must not be 0.");
tgtAssert(_callee != 0, "Target member function pointer must not be 0.");
}
/**
* Destructor, nothing to do here
*/
~CallMemberFuncJob() {};
/**
* Executes this job by calling the member function.
*/
virtual void execute() {
(_target->*_callee)();
}
protected:
T* _target; ///< Target object
void (T::*_callee)(); /// <Member function to call
};
/**
* Specific job, that is calling a member function pasing a single argument.
*/
template<class T, class A1>
class CallMemberFunc1ArgJob {
public:
/**
* Creates an new job, that is calling \a callee on \a target pasing \a arg1 as single argument.
* \param target Target object
* \param callee Member function to call
* \param arg1 Argument to pass to \a callee
*/
CallMemberFunc1ArgJob(T* target, void (T::*callee)(A1), const A1& arg1)
: _target(target)
, _callee(callee)
, _arg1(arg1)
{
tgtAssert(_target != 0, "Target object must not be 0.");
tgtAssert(_callee != 0, "Target member function pointer must not be 0.");
}
/**
* Destructor, nothing to do here
*/
~CallMemberFunc1ArgJob() {};
/**
* Executes this job by calling the member function.
*/
virtual void execute() {
(_target->*_callee)(_arg1);
}
protected:
T* _target; ///< Target object
void (T::*_callee)(A1); /// <Member function to call
const A1& _arg1; ///< Argument to pass to \a callee
};
}
#endif // JOB_H__
\ No newline at end of file
......@@ -27,7 +27,9 @@
// ================================================================================================
#include "jobpool.h"
#include "tgt/assert.h"
#include "core/tools/job.h"
namespace TUMVis {
......@@ -36,38 +38,38 @@ namespace TUMVis {
JobPool::JobPool()
: _queues(0)
{
_queues = new std::list<Job*>[NUM_PRIORITIES];
_queues = new tbb::concurrent_queue<AbstractJob*>[NUM_PRIORITIES];
}
JobPool::~JobPool() {
// delete jobs
AbstractJob* toDelete = 0;
for (size_t i = 0; i < NUM_PRIORITIES; ++i) {
for (std::list<Job*>::iterator it = _queues[i].begin(); it != _queues[i].end(); ++it) {
delete *it;
}
while (_queues[i].try_pop(toDelete))
delete toDelete;
}
// delete queues
delete[] _queues;
}
void JobPool::enqueueJob(Job* job, JobPriority priority) {
void JobPool::enqueueJob(AbstractJob* job, JobPriority priority) {
size_t i = static_cast<size_t>(priority);
tgtAssert(i < NUM_PRIORITIES, "Job priority index must be lower than the total number or priorities.");
tgtAssert(job != 0, "Job must not be 0");
_queues[i].push_back(job);
_queues[i].push(job);
s_enqueuedJob();
}
Job* JobPool::dequeueJob() {
AbstractJob* JobPool::dequeueJob() {
// very simple scheduling algorithm. This should be made fairer and avoid starving!
AbstractJob* toReturn = 0;
for (size_t i = 0; i < NUM_PRIORITIES; ++i) {
if (! _queues[i].empty()) {
Job* toReturn = _queues[i].front();
_queues[i].pop_front();
return toReturn;
}
if (_queues[i].try_pop(toReturn));
return toReturn;
}
return 0;
}
......
......@@ -29,15 +29,17 @@
#ifndef JOBPOOL_H__
#define JOBPOOL_H__
#include <list>
#include "sigslot/sigslot.h"
#include "tbb/include/tbb/concurrent_queue.h"
namespace TUMVis {
class Job;
class AbstractJob;
/**
* A JobPool manages multible Jobs in queues with different priorities.
*
* \note This class is to be considered as thread-safe.
* \todo Implement a suitable scheduling strategy to avoid starving of low priority jobs.
* This sounds like a good opportunity to take a look at the Betriebssysteme lecture slides. :)
*/
......@@ -52,8 +54,14 @@ namespace TUMVis {
Low = 2 ///< Low priority jobs are only considered if there are no jobs in the queue with higher priority
};
/**
* Creates a new JobPool
*/
JobPool();
/**
* Destructor, deletes all jobs which are still enqueued.
*/
~JobPool();
/**
......@@ -63,20 +71,22 @@ namespace TUMVis {
* \param job Job to enqueue, JobPool takes ownership of this Job!
* \param priority Priority of the job to enqueue
*/
void enqueueJob(Job* job, JobPriority priority);
void enqueueJob(AbstractJob* job, JobPriority priority);
/**
* Dequeues the next job according to the scheduling strategy.
* \note The calling function takes the ownership of the returned job!
* \todo Develop a good scheduling strategy and describe it here.
* \return The next job to execute, 0 if there is currently no job to execute.
* \return The next job to execute, 0 if there is currently no job to execute. The caller takes ownership of the job!
*/
Job* dequeueJob();
AbstractJob* dequeueJob();
/// Signal being emitted, when a job has been enqueued.
sigslot::signal0<> s_enqueuedJob;
protected:
static const size_t NUM_PRIORITIES;
std::list<Job*>* _queues; ///< Array of job queues, one for each JobPriority
static const size_t NUM_PRIORITIES; ///< total number of piorities, make sure that this matches the JobPriority enum.
tbb::concurrent_queue<AbstractJob*>* _queues; ///< Array of job queues, one for each JobPriority
};
}
......
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