abstractprocessor.h 11.3 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
        /**
         * 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
68
            INVALID_PROPERTIES  = 1 << 2    ///< Need to update the properties
69
        };
70

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

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

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


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

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

109 110 111 112 113 114
        /**
         * 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;

115 116 117 118 119 120
        /**
         * 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;

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

133 134 135 136 137 138 139 140 141 142 143
        /**
         * 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);
144 145 146 147 148 149 150 151 152 153 154 155

        /**
         * 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);
156
        
157
        /**
158
         * 
159
         * Locks all properties in the processor's PropertyCollection and marks them as "in use".
160
         * \sa  AbstractProcessor::unlockProcessor
161
         */
162
        void lockProcessor();
163 164 165

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

170 171 172 173 174 175
        /**
         * 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();
176

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
// = 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_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));
        }

254 255 256 257 258 259 260 261 262 263 264 265 266
        /**
         * Gets called from the pipeline before calling process(), when this processor has an INVALID_PROPERTIES level.
         * \note    You may overload this method as needed. The default implementation only validates
         *          the INVALID_PROPERTIES level again.
         * \note    There is also an overloadable updateProperties() in the HasPropertyCollection super class, 
         *          which is called from the processor itself. If you do not need access to the DataContainer
         *          of the parent pipeline, you can also use that method.
         * \see     HasPropertyCollection::updateProperties()
         * \param   dc  DataContainer   The DataContainer of the calling pipeline.
         */
        virtual void updateProperties(DataContainer& dc);


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

270 271 272
        /// Signal emitted when the processor has been validated.
        sigslot::signal1<AbstractProcessor*> s_validated;

273 274
// = Slots ========================================================================================

schultezub's avatar
schultezub committed
275 276 277 278 279 280
        /**
         * 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
281
    protected:
282
        tbb::atomic<bool> _enabled;                 ///< flag whether this processor is currently enabled
283
        tbb::atomic<bool> _clockExecutionTime;      ///< flag whether to measure the execution time of this processor
284 285 286 287

        /// 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
288

289
    private:
290 291
        tbb::atomic<int> _level;            ///< current invalidation level
        tbb::concurrent_queue<int> _queuedInvalidations;
292

293
        static const std::string loggerCat_;
schultezub's avatar
schultezub committed
294 295 296 297 298
    };

}

#endif // PROCESSOR_H__