abstractprocessor.h 10.8 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, all rights reserved,
schultezub's avatar
schultezub committed
6
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
7
8
9
//      Chair for Computer Aided Medical Procedures
//      Technische Universität München
//      Boltzmannstr. 3, 85748 Garching b. München, Germany
schultezub's avatar
schultezub committed
10
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
// 
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// 
// ================================================================================================

schultezub's avatar
schultezub committed
30
31
32
#ifndef PROCESSOR_H__
#define PROCESSOR_H__

schultezub's avatar
schultezub committed
33
#include "sigslot/sigslot.h"
schultezub's avatar
schultezub committed
34
#include "tbb/atomic.h"
35
#include "tbb/concurrent_queue.h"
schultezub's avatar
schultezub committed
36
37
#include "tgt/logmanager.h"
#include "core/datastructures/datacontainer.h"
schultezub's avatar
schultezub committed
38
39
40
41
#include "core/properties/propertycollection.h"

#include <string>
#include <vector>
schultezub's avatar
schultezub committed
42

schultezub's avatar
schultezub committed
43
namespace campvis {
schultezub's avatar
schultezub committed
44
45
    class AbstractProperty;

schultezub's avatar
schultezub committed
46
    /**
schultezub's avatar
schultezub committed
47
     * Abstract base class for CAMPVis Processors.
48
49
50
51
52
53
54
55
     * A processor implements a specific task, which it performs on the DataCollection passed
     * during process(). Properties provide a transparent layer for adjusting the processor's 
     * behaviour.
     * Once a processor has finished it sets it should set its invalidation level to valid. As
     * soon as one of its properties changes, the processor will be notified and possibliy
     * change its invalidation level. Observing pipelines will be notified of this and can
     * and have to decide which part of the pipeline has to be re-evaluated wrt. the processor's
     * invalidation level.
schultezub's avatar
schultezub committed
56
57
58
     * 
     * \sa AbstractPipeline
     */
schultezub's avatar
schultezub committed
59
    class AbstractProcessor : public HasPropertyCollection {
schultezub's avatar
schultezub committed
60
    public:
61
62
63
64
65
66
67
68
69
70
        /**
         * Available invalidation levels
         */
        enum InvalidationLevel {
            VALID               = 0,        ///< Valid
            INVALID_RESULT      = 1 << 0,   ///< Need to rerun the process() method
            INVALID_SHADER      = 1 << 1,   ///< Need to recompile the shader
            INVALID_FILE        = 1 << 2,   ///< Need to reread the file
            INVALID_PROPERTIES  = 1 << 3    ///< Need to update the properties
        };
71

72
73
74
75
76
77
78
        /// Current state of a processor in terms of stability.
        enum ProcessorState {
            EXPERIMENTAL,
            TESTING,
            STABLE
        };

schultezub's avatar
schultezub committed
79
80
81
82
83
84
85
86
87
88
89
        /**
         * Creates a AbstractProcessor.
         */
        AbstractProcessor();

        /**
         * Virtual Destructor
         **/
        virtual ~AbstractProcessor();


schultezub's avatar
schultezub committed
90
        /**
91
92
93
         * Initializes the processor.
         * Everything that requires a valid OpenGL context or is otherwise expensive gets in here.
         * 
schultezub's avatar
schultezub committed
94
95
96
         * \note    When overwriting this method, make sure to call the base class version first.
         */
        virtual void init();
97
98
        
        /**
schultezub's avatar
schultezub committed
99
         * Deinitializes this processor.
100
         * \note    When overwriting this method, make sure to call the base class version at the end.
101
102
         */
        virtual void deinit();
schultezub's avatar
schultezub committed
103

schultezub's avatar
schultezub committed
104
105
        /**
         * Execute this processor.
106
         * \param data      DataContainer to work on.
schultezub's avatar
schultezub committed
107
         **/
108
        virtual void process(DataContainer& data) = 0;
schultezub's avatar
schultezub committed
109

110
111
112
113
114
115
        /**
         * Gets the name of this very processor. To be defined by every subclass.
         * \return  The name of this processor.
         */
        virtual const std::string getName() const = 0;

116
117
118
119
120
121
        /**
         * Gets a description of this processor. To be defined by every subclass.
         * \return  A description what this processor does.
         */
        virtual const std::string getDescription() const = 0;

122
123
124
125
126
127
128
129
130
131
132
133
        /**
         * Gets the name of the author of this processor. Can be handy if you have questions on how to do XYZ with this processor.
         * \return  The name of the author of this processor.
         */
        virtual const std::string getAuthor() const = 0;

        /**
         * Gets the current processor state in terms of stability. To be defined by every subclass.
         * \return  The current processor state in terms of stability.
         */
        virtual const ProcessorState getProcessorState() const = 0;

134
135
136
137
138
139
140
141
142
143
144
        /**
         * Gets the flag whether this processor is currently enabled.
         * \return _enabled
         */
        bool getEnabled() const;

        /**
         * Sets the flag whether this processor is currently enabled.
         * \param   enabled     New flag whether this processor is currently enabled.
         */
        void setEnabled(bool enabled);
145
146
147
148
149
150
151
152
153
154
155
156

        /**
         * Returns whether to measure the execution time of this processor.
         * \return  _clockExecutionTime
         */
        bool getClockExecutionTime() const;

        /**
         * Sets whether to measure the execution time of this processor.
         * \param   value   The new flag vlaue whether to measure the execution time of this processor.
         */
        void setClockExecutionTime(bool value);
157
        
158
        /**
159
         * 
160
         * Locks all properties in the processor's PropertyCollection and marks them as "in use".
161
         * \sa  AbstractProcessor::unlockProcessor
162
         */
163
        void lockProcessor();
164
165
166

        /**
         * Unlocks all properties in the processor's PropertyCollection and marks them as "not in use".
167
         * \sa  AbstractProcessor::lockProcessor
168
         */
169
        void unlockProcessor();
170

171
172
173
174
175
176
        /**
         * Returns the current lockProcessor status of this processor.
         * If a processor is locked, all of its properties are locked and its process method must not be called.
         * \return  _locked != 0
         */
        bool isLocked();
177

178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
// = Invalidation Level related stuff =============================================================

        /**
         * Returns the current invalidation level.
         * \return _level
         */
        int getInvalidationLevel() const {
            return _level;
        }

        /**
         * Returns wheter the invalidation level is valid (i.e. no invalid flag is set).
         * \return _level == VALID
         */
        bool isValid() const {
            return _level == static_cast<int>(VALID);
        }

        /**
         * Returns wheter the the INVALID_RESULT flag is set.
         * \return _level & INVALID_RESULT
         */
        bool hasInvalidResult() const {
            return (_level & static_cast<int>(INVALID_RESULT)) != 0;
        }

        /**
         * Returns wheter the the INVALID_SHADER flag is set.
         * \return _level & INVALID_SHADER
         */
        bool hasInvalidShader() const {
            return (_level & static_cast<int>(INVALID_SHADER)) != 0;
        }

        /**
         * Returns wheter the the INVALID_FILE flag is set.
         * \return _level & INVALID_FILE
         */
        bool hasInvalidFile() const {
            return (_level & static_cast<int>(INVALID_FILE)) != 0;
        }

        /**
         * Returns wheter the the INVALID_PROPERTIES flag is set.
         * \return _level & INVALID_PROPERTIES
         */
        bool hasInvalidProperties() const {
            return (_level & static_cast<int>(INVALID_PROPERTIES)) != 0;
        }

        /**
         * Sets the invalidation level to valid (i.e. clears all invalidation flags).
         */
        void setValid() {
            _level = static_cast<int>(VALID);
        }

        /**
         * Sets all invalidation flags specified in \a level.
         * \param   level   Flags to set to invalid.
         */
        void invalidate(int level);

        /**
         * Sets all invalidation flags specified in \a il's level.
         * \param   il  Flags to set to invalid.
         */
        void invalidate(InvalidationLevel il) {
            invalidate(static_cast<int>(il));
        }

        /**
         * Clears all invalidation flags specified in \a level.
         * \param   level   Flags to set to valid.
         */
        void validate(int level);

        /**
         * Clears all invalidation flags specified in \a il's level.
         * \param   il  Flags to set to valid.
         */
        void validate(InvalidationLevel il) {
            validate(static_cast<int>(il));
        }

schultezub's avatar
schultezub committed
263
        /// Signal emitted when the processor has been invalidated.
264
        sigslot::signal1<AbstractProcessor*> s_invalidated;
schultezub's avatar
schultezub committed
265

266
267
268
        /// Signal emitted when the processor has been validated.
        sigslot::signal1<AbstractProcessor*> s_validated;

269
270
// = Slots ========================================================================================

schultezub's avatar
schultezub committed
271
272
273
274
275
276
        /**
         * Slot getting called when one of the observed properties changed and notifies its observers.
         * \param   prop    Property that emitted the signal
         */
        virtual void onPropertyChanged(const AbstractProperty* prop);

schultezub's avatar
schultezub committed
277
    protected:
278
        tbb::atomic<bool> _enabled;                 ///< flag whether this processor is currently enabled
279
        tbb::atomic<bool> _clockExecutionTime;      ///< flag whether to measure the execution time of this processor
280
281
282
283

        /// Flag whether this processor is currently locked
        /// (This implies, that all properties are locked and it is not valid to call process())
        tbb::atomic<bool> _locked;
schultezub's avatar
schultezub committed
284

285
    private:
286
287
        tbb::atomic<int> _level;            ///< current invalidation level
        tbb::concurrent_queue<int> _queuedInvalidations;
288

289
        static const std::string loggerCat_;
schultezub's avatar
schultezub committed
290
291
292
293
294
    };

}

#endif // PROCESSOR_H__