Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

abstractprocessor.cpp 6.14 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-2015, 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 "abstractprocessor.h"
26
#include "cgt/assert.h"
27
#include "core/properties/abstractproperty.h"
28

29
30
#include <ext/threading.h>

schultezub's avatar
schultezub committed
31
namespace campvis {
schultezub's avatar
schultezub committed
32

schultezub's avatar
schultezub committed
33
    const std::string AbstractProcessor::loggerCat_ = "CAMPVis.core.datastructures.Processor";
schultezub's avatar
schultezub committed
34
35


36
37
38
    AbstractProcessor::AbstractProcessor()
        : HasPropertyCollection()
    {
39
        _enabled = true;
40
        _clockExecutionTime = false;
41
        _ignorePropertyChanges = 0;
42
        _locked = 0;
43
        _level = VALID;
schultezub's avatar
schultezub committed
44
45
46
47
48
49
    }

    AbstractProcessor::~AbstractProcessor() {

    }

schultezub's avatar
schultezub committed
50
    void AbstractProcessor::init() {
schultezub's avatar
schultezub committed
51
        initAllProperties();
52
    }
schultezub's avatar
schultezub committed
53

54
    void AbstractProcessor::deinit() {
schultezub's avatar
schultezub committed
55
        deinitAllProperties();
schultezub's avatar
schultezub committed
56
57
    }

58

59
    void AbstractProcessor::lockProcessor() {
60
61
        // hopefully, it does not take too long.
        while (_locked.compare_and_swap(true, false) == true)
62
            std::this_thread::yield();
63
        _locked = true;
schultezub's avatar
schultezub committed
64
        lockAllProperties();
65
66
    }

67
    void AbstractProcessor::unlockProcessor() {
68
        cgtAssert(_locked == true, "Called AbstractProcessor::unlockProcessor() on unlocked processor!");
schultezub's avatar
schultezub committed
69
        unlockAllProperties();
70
71
72
73
74
        int summed = VALID;
        int il;
        while (_queuedInvalidations.try_pop(il)) {
            summed |= il;
        }
75
        _locked = false;
schultezub's avatar
schultezub committed
76
77
78

        if (summed != VALID)
            invalidate(summed);
79
80
81
82
    }

    bool AbstractProcessor::isLocked() {
        return _locked != 0;
83
84
    }

schultezub's avatar
schultezub committed
85
    void AbstractProcessor::onPropertyChanged(const AbstractProperty* prop) {
86
87
88
89
90
91
92
93
        if (_ignorePropertyChanges == 0) {
            tbb::spin_rw_mutex::scoped_lock lock(_mtxInvalidationMap, false);
            auto it = _invalidationMap.find(prop);
            if (it != _invalidationMap.end())
                invalidate(it->second);
            else
                LDEBUG("Caught an property changed signal that was not registered with an invalidation level. Did you forget to call addProperty()?");
        }
schultezub's avatar
schultezub committed
94
    }
95

96
97
98
99
100
101
102
103
    bool AbstractProcessor::getEnabled() const {
        return _enabled;
    }

    void AbstractProcessor::setEnabled(bool enabled) {
        _enabled = enabled;
    }

104
    void AbstractProcessor::invalidate(int level) {
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
105
106
107
        if (level == 0)
            return;

108
109
110
111
112
113
114
115
116
        if (_locked) {
            // TODO: this is not 100% thread-safe - an invalidation might slip through if the processor is unlocked during invalidation
            _queuedInvalidations.push(level);
        }
        else {
            int tmp;
            do {
                tmp = _level;
            } while (_level.compare_and_swap(tmp | level, tmp) != tmp);
117
            s_invalidated.emitSignal(this);
118
        }
119
120
121
122
123
124
125
    }

    void AbstractProcessor::validate(int level) {
        int tmp;
        do {
            tmp = _level;
        } while (_level.compare_and_swap(tmp & (~level), tmp) != tmp);
126
        s_validated.emitSignal(this);
127
128
    }

129
130
131
132
133
134
135
136
    bool AbstractProcessor::getClockExecutionTime() const {
        return _clockExecutionTime;
    }

    void AbstractProcessor::setClockExecutionTime(bool value) {
        _clockExecutionTime = value;
    }

137

138
    void AbstractProcessor::process(DataContainer& data) {
139
140
141
142
143
144
145
146
147
        if (hasInvalidShader()) {
            updateShader();
            validate(INVALID_SHADER);
        }
        if (hasInvalidProperties()) {
            updateProperties(data);
            validate(INVALID_PROPERTIES);
        }

148
        // use a scoped lock for exception safety
149
        AbstractProcessor::ScopedLock lock(this);
150
        cgtAssert(_locked == true, "Processor not locked, this should not happen!");
151

152
        if (hasInvalidResult()) {
153
            updateResult(data);
154
155
            validate(INVALID_RESULT);
        }
156
157
    }

158
159
160
161
162
    void AbstractProcessor::forceProcess(DataContainer& dataContainer, int invalidationLevel) {
        invalidate(invalidationLevel);
        process(dataContainer);
    }

163
164
165
166
    void AbstractProcessor::updateShader() {
        LDEBUG("Called non-overriden updateShader() in " << getName() << ". Did you forget to override your method?");
    }

167
    void AbstractProcessor::updateProperties(DataContainer& dc) {
168
        LDEBUG("Called non-overriden updateProperties() in " << getName() << ". Did you forget to override your method?");
169
170
    }

171
    void AbstractProcessor::addProperty(AbstractProperty& prop, int invalidationLevel /* = INVALID_RESULT*/) {
172
173
174
175
176
177
178
179
        HasPropertyCollection::addProperty(prop);
        setPropertyInvalidationLevel(prop, invalidationLevel);
    }

    void AbstractProcessor::setPropertyInvalidationLevel(AbstractProperty& prop, int invalidationLevel) {
        tbb::spin_rw_mutex::scoped_lock lock(_mtxInvalidationMap, true);
        _invalidationMap[&prop] = invalidationLevel;
    }
180
181
182
183
184
185
186
    void AbstractProcessor::ignorePropertyChanges() {
        ++_ignorePropertyChanges;
    }

    void AbstractProcessor::observePropertyChanges() {
        --_ignorePropertyChanges;
    }
schultezub's avatar
schultezub committed
187
}