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.62 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 == 0 || _enabled == false)
66
67
68
69
70
71
72
73
            return;

        tbb::concurrent_hash_map<AbstractProcessor*, bool>::const_accessor a;
        if (_isVisProcessorMap.find(a, processor)) {
            if (a->second) {
                // is VisualizationProcessor
                GLJobProc.enqueueJob(
                    _canvas, 
74
                    makeJobOnHeap<AutoEvaluationPipeline, AbstractProcessor*>(this, &AutoEvaluationPipeline::executeProcessorAndCheckOpenGLState, processor), 
75
76
77
                    OpenGLJobProcessor::SerialJob);
            }
            else {
78
                SimpleJobProc.enqueueJob(makeJob<AutoEvaluationPipeline, AbstractProcessor*>(this, &AutoEvaluationPipeline::executeProcessor, processor));
79
80
81
82
83
84
85
86
            }
        }
        else {
            tgtAssert(false, "Could not find processor in processor map.");
            LWARNING("Caught invalidation of a non-registered processor!");
        }
    }

87
    void AutoEvaluationPipeline::addProcessor(AbstractProcessor* processor) {
88
        _isVisProcessorMap.insert(std::make_pair(processor, (dynamic_cast<VisualizationProcessor*>(processor) != 0)));
89
        findDataNamePropertiesAndAddToPortMap(processor);
90

91
92
93
        AbstractPipeline::addProcessor(processor);
    }

94
    void AutoEvaluationPipeline::onDataNamePropertyChanged(const AbstractProperty* prop) {
95
96
        // static_cast is safe since this slot only get called for DataNameProperties
        // const_cast is not beautiful but safe here as well
97
98
        DataNameProperty* dnp = const_cast<DataNameProperty*>(static_cast<const DataNameProperty*>(prop));

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

111
                // acquire read-lock since we add the new value to the port map
112
                tbb::spin_rw_mutex::scoped_lock lock(_pmMutex, false);
113
114

                // insert new value into port map and update the reference in the iterator map
115
116
117
118
                std::pair<PortMapType::iterator, bool> result = _portMap.insert(std::make_pair(dnp->getValue(), dnp));
                if (result.second) {
                    it->second = result.first;
                }
119
120
121

                // sanity check, if this assertion fails, we have a problem...
                tgtAssert(result.second, "Could not insert Property into port map!");
122
123
124
            }
        }
        else {
125
            // this should not happen, otherwise we did something wrong before.
126
127
128
129
            tgtAssert(false, "Could not find Property in iterator map!");
        }
    }

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

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

        AbstractPipeline::onDataContainerDataAdded(name, dh);
    }

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
}