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.54 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

27
#include "cgt/cgt_gl.h"
28
#include "cgt/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

        _data->s_dataAdded.connect(this, &AutoEvaluationPipeline::onDataContainerDataAdded);
54
55
    }

56
    void AutoEvaluationPipeline::deinit() {
57
58
        _data->s_dataAdded.disconnect(this);

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

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

70
        setPipelineDirty();
71
72
    }

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

77
78
79
        AbstractPipeline::addProcessor(processor);
    }

80
    void AutoEvaluationPipeline::executePipeline() {
81
82
        // execute each processor once 
        // (AbstractProcessor::process() takes care of executing only invalid processors)
83
        for (size_t i = 0; i < _processors.size(); ++i) {
84
            executeProcessorAndCheckOpenGLState(_processors[i]);
85
86
87
        }
    }

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

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

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

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

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

124
125
126
127
128
129
130
131
132
133
134
    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);
        }
    }

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

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

150
151
152
153
154
155
156
157
158
159
    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));
160
                    cgtAssert(result.second, "Could not insert Property into port map!");
161
162
163
164
165
166
167
168
169
170
171
172
173
                    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);
            }
        }
    }

174
}