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

autoevaluationpipeline.cpp 7.44 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"
26

schultezub's avatar
schultezub committed
27
#include "tgt/tgt_gl.h"
schultezub's avatar
schultezub committed
28
#include "tgt/glcanvas.h"
29

30
#include "core/pipeline/visualizationprocessor.h"
31
#include "core/properties/datanameproperty.h"
32
#include "core/properties/metaproperty.h"
33

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

37
38
    AutoEvaluationPipeline::AutoEvaluationPipeline(DataContainer* dc) 
        : AbstractPipeline(dc)
39
40
41
    {
    }

42
    AutoEvaluationPipeline::~AutoEvaluationPipeline() {
43
44
    }

45
    void AutoEvaluationPipeline::init() {
46
        AbstractPipeline::init();
schultezub's avatar
schultezub committed
47

48
49
50
        // 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
51
        }
52
53
    }

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

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

66
        setPipelineDirty();
67
68
    }

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

73
74
75
        AbstractPipeline::addProcessor(processor);
    }

76
77
78
79
80
81
82
83
84
    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());
            }
        }
    }

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

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

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

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

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

121
122
123
124
125
126
127
128
129
130
131
    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);
        }
    }

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

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

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

171
}