autoevaluationpipeline.cpp 7.55 KB
Newer Older
1 2
// ================================================================================================
// 
schultezub's avatar
schultezub committed
3
// This file is part of the CAMPVis Software Framework.
4
// 
5
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
schultezub's avatar
schultezub committed
6
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
7
//      Chair for Computer Aided Medical Procedures
8 9
//      Technische Universitaet Muenchen
//      Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
10
// 
schultezub's avatar
schultezub committed
11
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
12
// 
13 14 15 16
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 
// except in compliance with the License. You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
17
// 
18 19 20 21
// Unless required by applicable law or agreed to in writing, software distributed under the 
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
// either express or implied. See the License for the specific language governing permissions 
// and limitations under the License.
22 23 24
// 
// ================================================================================================

25
#include "autoevaluationpipeline.h"
schultezub's avatar
schultezub committed
26
#include "tgt/tgt_gl.h"
schultezub's avatar
schultezub committed
27
#include "tgt/glcanvas.h"
28
#include "core/pipeline/visualizationprocessor.h"
29
#include "core/properties/datanameproperty.h"
30
#include "core/properties/metaproperty.h"
31 32
#include "core/tools/job.h"
#include "core/tools/opengljobprocessor.h"
33
#include "core/tools/simplejobprocessor.h"
34

35

schultezub's avatar
schultezub committed
36
namespace campvis {
37
    const std::string AutoEvaluationPipeline::loggerCat_ = "CAMPVis.core.datastructures.AutoEvaluationPipeline";
38

39 40
    AutoEvaluationPipeline::AutoEvaluationPipeline(DataContainer* dc) 
        : AbstractPipeline(dc)
41 42 43
    {
    }

44
    AutoEvaluationPipeline::~AutoEvaluationPipeline() {
45 46
    }

47
    void AutoEvaluationPipeline::init() {
48
        AbstractPipeline::init();
schultezub's avatar
schultezub committed
49

50 51 52
        // connect invalidation of each processor
        for (std::vector<AbstractProcessor*>::iterator it = _processors.begin(); it != _processors.end(); ++it) {
            (*it)->s_invalidated.connect(this, &AutoEvaluationPipeline::onProcessorInvalidated);
schultezub's avatar
schultezub committed
53
        }
54 55
    }

56 57 58
    void AutoEvaluationPipeline::deinit() {
        for (std::vector<AbstractProcessor*>::iterator it = _processors.begin(); it != _processors.end(); ++it) {
            (*it)->s_invalidated.disconnect(this);
59
        }
60 61
    
        AbstractPipeline::deinit();
62 63
    }

64
    void AutoEvaluationPipeline::onProcessorInvalidated(AbstractProcessor* processor) {
65
        if (_canvas == nullptr || getEnabled() == false)
66 67
            return;

68
        setPipelineDirty();
69 70
    }

71
    void AutoEvaluationPipeline::addProcessor(AbstractProcessor* processor) {
72
        _isVisProcessorMap.insert(std::make_pair(processor, (dynamic_cast<VisualizationProcessor*>(processor) != 0)));
73
        findDataNamePropertiesAndAddToPortMap(processor);
74

75 76 77
        AbstractPipeline::addProcessor(processor);
    }

78 79 80 81 82 83 84 85 86
    void AutoEvaluationPipeline::executePipeline() {
        // execute each processor (we do this n*n times, as we might have a complex dependency graph)
        for (size_t i = 0; i < _processors.size(); ++i) {
            for (size_t i = 0; i < _processors.size(); ++i) {
                _processors[i]->process(getDataContainer());
            }
        }
    }

87
    void AutoEvaluationPipeline::onDataNamePropertyChanged(const AbstractProperty* prop) {
88 89
        // static_cast is safe since this slot only get called for DataNameProperties
        // const_cast is not beautiful but safe here as well
90 91
        DataNameProperty* dnp = const_cast<DataNameProperty*>(static_cast<const DataNameProperty*>(prop));

92
        // find string-iterator pair for the given property
93 94
        IteratorMapType::iterator it = _iteratorMap.find(dnp);
        if (it != _iteratorMap.end()) {
95 96
            // check whether the value of the DataNameProperty differs from the one in our port map
            // i.e.: We need to update the port map
97 98
            if (dnp->getValue() != it->second->first) {
                {
99
                    // acquire a write-lock since we erase the old value from our port map
100 101 102 103
                    tbb::spin_rw_mutex::scoped_lock lock(_pmMutex, true);
                    _portMap.unsafe_erase(it->second);
                }

104
                // acquire read-lock since we add the new value to the port map
105
                tbb::spin_rw_mutex::scoped_lock lock(_pmMutex, false);
106 107

                // insert new value into port map and update the reference in the iterator map
108 109 110 111
                std::pair<PortMapType::iterator, bool> result = _portMap.insert(std::make_pair(dnp->getValue(), dnp));
                if (result.second) {
                    it->second = result.first;
                }
112 113 114

                // sanity check, if this assertion fails, we have a problem...
                tgtAssert(result.second, "Could not insert Property into port map!");
115 116 117
            }
        }
        else {
118
            // this should not happen, otherwise we did something wrong before.
119 120 121 122
            tgtAssert(false, "Could not find Property in iterator map!");
        }
    }

123 124 125 126 127 128 129 130 131 132 133
    namespace {
        /// Local helper function to recursively emit the s_changed signal for the given
        /// properties and all of its shared properties.
        void recursiveEmitSignal(DataNameProperty* p) {
            std::set<AbstractProperty*> v = p->getSharedProperties();
            for (auto it = v.begin(); it != v.end(); ++it)
                recursiveEmitSignal(static_cast<DataNameProperty*>(*it));
            p->s_changed.emitSignal(p);
        }
    }

134
    void AutoEvaluationPipeline::onDataContainerDataAdded(std::string name, DataHandle dh) {
135
        {
136
            // acquire read lock
137
            tbb::spin_rw_mutex::scoped_lock lock(_pmMutex, false);
138 139

            // find all DataNameProperties in the port map that have name as current value
140
            PortMapType::const_iterator it = _portMap.find(name);
141 142
            while (it != _portMap.end() && it->first == name) {
                // invalidate those properties by emitting changed signal
143
                recursiveEmitSignal(it->second);
144 145 146 147 148
                ++it;
            }
        }
    }

149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
    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);
            }
        }
    }

173
}