05.11., 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Extended AutoEvaluationPipeline to also support nested DataNameProperties:

AutoEvaluationPipeline now also looks recursively for DataNameProperties in MetaProperties of its processors. Hence, it simulates ports also for nested processors. Furthermore, improved AutoEvaluationPipeline's documentation.
parent 8d26da04
......@@ -27,6 +27,7 @@
#include "tgt/glcanvas.h"
#include "core/pipeline/visualizationprocessor.h"
#include "core/properties/datanameproperty.h"
#include "core/properties/metaproperty.h"
#include "core/tools/job.h"
#include "core/tools/opengljobprocessor.h"
#include "core/tools/simplejobprocessor.h"
......@@ -85,57 +86,57 @@ namespace campvis {
void AutoEvaluationPipeline::addProcessor(AbstractProcessor* processor) {
_isVisProcessorMap.insert(std::make_pair(processor, (dynamic_cast<VisualizationProcessor*>(processor) != 0)));
PropertyCollection pc = processor->getProperties();
for (size_t i = 0; i < pc.size(); ++i) {
if (DataNameProperty* dnp = dynamic_cast<DataNameProperty*>(pc[i])) {
if (dnp->getAccessInfo() == DataNameProperty::READ) {
tbb::spin_rw_mutex::scoped_lock lock(_pmMutex, false);
std::pair<PortMapType::iterator, bool> result = _portMap.insert(std::make_pair(dnp->getValue(), dnp));
tgtAssert(result.second, "Could not insert Property into port map!");
if (result.second) {
_iteratorMap[dnp] = result.first;
dnp->s_changed.connect(this, &AutoEvaluationPipeline::onDataNamePropertyChanged);
}
}
}
}
findDataNamePropertiesAndAddToPortMap(processor);
AbstractPipeline::addProcessor(processor);
}
void AutoEvaluationPipeline::onDataNamePropertyChanged(const AbstractProperty* prop) {
// static_cast is safe since this slot only get called for DataNameProperties
// const_cast is not beautiful but safe here as well
DataNameProperty* dnp = const_cast<DataNameProperty*>(static_cast<const DataNameProperty*>(prop));
// find string-iterator pair
// find string-iterator pair for the given property
IteratorMapType::iterator it = _iteratorMap.find(dnp);
if (it != _iteratorMap.end()) {
// check whether the value of the DataNameProperty differs from the one in our port map
// i.e.: We need to update the port map
if (dnp->getValue() != it->second->first) {
{
// acquire a write-lock since we erase the old value from our port map
tbb::spin_rw_mutex::scoped_lock lock(_pmMutex, true);
// value of the property has changed
_portMap.unsafe_erase(it->second);
}
// acquire read-lock since we add the new value to the port map
tbb::spin_rw_mutex::scoped_lock lock(_pmMutex, false);
// insert new value into port map and update the reference in the iterator map
std::pair<PortMapType::iterator, bool> result = _portMap.insert(std::make_pair(dnp->getValue(), dnp));
tgtAssert(result.second, "Could not insert Property into port map!");
if (result.second) {
it->second = result.first;
}
// sanity check, if this assertion fails, we have a problem...
tgtAssert(result.second, "Could not insert Property into port map!");
}
}
else {
// this should not happen, otherwise we did something wrong before.
tgtAssert(false, "Could not find Property in iterator map!");
}
}
void AutoEvaluationPipeline::onDataContainerDataAdded(const std::string& name, const DataHandle& dh) {
{
// acquire read lock
tbb::spin_rw_mutex::scoped_lock lock(_pmMutex, false);
// find all DataNameProperties in the port map that have name as current value
PortMapType::const_iterator it = _portMap.find(name);
while(it != _portMap.end() && it->first == name) {
it->second->setValue(it->second->getValue());
while (it != _portMap.end() && it->first == name) {
// invalidate those properties by emitting changed signal
it->second->s_changed(it->second);
++it;
}
}
......@@ -143,4 +144,28 @@ namespace campvis {
AbstractPipeline::onDataContainerDataAdded(name, dh);
}
void AutoEvaluationPipeline::findDataNamePropertiesAndAddToPortMap(const HasPropertyCollection* hpc) {
const PropertyCollection& pc = hpc->getProperties();
// traverse property collection
for (size_t i = 0; i < pc.size(); ++i) {
if (DataNameProperty* dnp = dynamic_cast<DataNameProperty*>(pc[i])) {
// if DataNameProperty, add to port map and register to changed signal
if (dnp->getAccessInfo() == DataNameProperty::READ) {
tbb::spin_rw_mutex::scoped_lock lock(_pmMutex, false);
std::pair<PortMapType::iterator, bool> result = _portMap.insert(std::make_pair(dnp->getValue(), dnp));
tgtAssert(result.second, "Could not insert Property into port map!");
if (result.second) {
_iteratorMap[dnp] = result.first;
dnp->s_changed.connect(this, &AutoEvaluationPipeline::onDataNamePropertyChanged);
}
}
}
else if (MetaProperty* mp = dynamic_cast<MetaProperty*>(pc[i])) {
// if MetaProperty, recursively check its PropertyCollection
findDataNamePropertiesAndAddToPortMap(mp);
}
}
}
}
......@@ -71,19 +71,36 @@ namespace campvis {
*/
virtual void onProcessorInvalidated(AbstractProcessor* processor);
static const std::string loggerCat_;
private:
/**
* Callback slot called if one of the DataNameProperties in the port map has changed.
* \param prop DataNameProperty that has changed.
*/
void onDataNamePropertyChanged(const AbstractProperty* prop);
/**
* Gets called when the data collection of this pipeline has changed and thus has notified its observers.
* If \a name equals the name of the renderTarget, the s_renderTargetChanged signal will be emitted.
* \param name Name of the added data.
* \param dh DataHandle to the newly added data.
*/
virtual void onDataContainerDataAdded(const std::string& name, const DataHandle& dh);
/**
* Recursively looks for all DataNameProperties in \a pc and adds them to the port map.
* If \a pc contains a MetaProperty, it will be seached recursively.
* \param pc PropertyCollection to search for DataNameProperties.
*/
void findDataNamePropertiesAndAddToPortMap(const HasPropertyCollection* pc);
/// Hashmap storing for each processor whether it's a VisualizationProcessor or not.
tbb::concurrent_hash_map<AbstractProcessor*, bool> _isVisProcessorMap;
/// PortMap typedef mapping a string to a set of DataNameProperties using a concurrent unordered multimap
typedef tbb::concurrent_unordered_multimap<std::string, DataNameProperty*> PortMapType;
/// IteratorMap typedef mapping a DataNameProperty to an iterator in a PortMap using a concurrent unordered map
typedef tbb::concurrent_unordered_map<DataNameProperty*, PortMapType::iterator> IteratorMapType;
/// Multimap to simulate ports between processors
......
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