genericproperty.h 8.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
//      Chair for Computer Aided Medical Procedures
8
9
//      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 GENERICPROPERTY_H__
#define GENERICPROPERTY_H__

33
#include <tbb/spin_mutex.h>
schultezub's avatar
 
schultezub committed
34
#include "tgt/logmanager.h"
schultezub's avatar
schultezub committed
35
#include "core/properties/abstractproperty.h"
schultezub's avatar
 
schultezub committed
36

schultezub's avatar
schultezub committed
37
namespace campvis {
schultezub's avatar
 
schultezub committed
38
39

    /**
schultezub's avatar
schultezub committed
40
41
42
     * Generic class for value-based properties.
     *
     * \tparam  T   Base type of the property's value.
43
     * \todo    Add PropertyWidgets, review use of mutex
schultezub's avatar
 
schultezub committed
44
45
     */
    template<typename T>
schultezub's avatar
schultezub committed
46
    class GenericProperty : public AbstractProperty {
schultezub's avatar
 
schultezub committed
47
48
    public:
        /**
schultezub's avatar
schultezub committed
49
50
51
52
         * Creates a new GenericProperty.
         * \param name      Property name
         * \param title     Property title (e.g. used for GUI)
         * \param value     Initial value of the property
53
         * \param invalidationLevel  Invalidation level that this property triggers
schultezub's avatar
 
schultezub committed
54
         */
schultezub's avatar
schultezub committed
55
56
57
58
        GenericProperty(
            const std::string& name,
            const std::string& title,
            const T& value,
59
            int invalidationLevel = AbstractProcessor::INVALID_RESULT);
schultezub's avatar
 
schultezub committed
60
61
62
63
64
65
66

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


67
68
69
70
71
72
73
74
        /**
         * Adds the given property \a prop to the set of shared properties.
         * All shared properties will be changed when this property changes.
         * \note        Make sure not to build circular sharing or you will encounter endless loops!
         * \param prop  Property to add, must be of the same type as this property.
         */
        virtual void addSharedProperty(AbstractProperty* prop);

schultezub's avatar
schultezub committed
75
76
77
78
        /**
         * Returns the current value of this property.
         * \return _value
         */
schultezub's avatar
schultezub committed
79
        const T& getValue() const;
schultezub's avatar
 
schultezub committed
80

schultezub's avatar
schultezub committed
81
        /**
82
         * On successful validation it sets the property value to \a value and notifies all observers.
83
         * Depending on the current lock state of the property, the value will either be written to the front or back buffer.
84
         * \sa GenericProperty::validateValue
schultezub's avatar
schultezub committed
85
86
         * \param value     New value for this property.
         */
87
        virtual void setValue(const T& value);
schultezub's avatar
 
schultezub committed
88
89


90
91
92
93
94
        /**
         * Unlocks the property. If the back buffer has changed, the changes will be written to the front
         * buffer and all observers will be notified.
         * \sa  GenericProperty::lock
         */
schultezub's avatar
schultezub committed
95
        virtual void unlock();
96
97


schultezub's avatar
schultezub committed
98
    protected:
99
100
101
102
103
104
105
106

        /**
         * Adapts \a value, so that is is a valid value for this property.
         * Default implementation does nothing and always returns \a value, subclasses can overwrite this method to fit their needs.
         * \param   value   value to validate.
         */
        virtual T validateValue(const T& value);

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
        /**
         * Sets the property value to \a value and notifies all observers.
         * \note    _localMutex has to be acquired before calling!
         * \param   value   New value for _value.
         */
        void setFrontValue(const T& value);

        /**
         * Sets the property's back buffer value to \a value.
         * \note    _localMutex has to be acquired before calling!
         * \param   value   New value for _backBuffer.
         */
        void setBackValue(const T& value);

        
        T _value;                               ///< value of the property
        T _backBuffer;                          ///< back buffer for values when property is in use
124

schultezub's avatar
schultezub committed
125
126
        static const std::string loggerCat_;
    };
schultezub's avatar
 
schultezub committed
127

schultezub's avatar
schultezub committed
128
129
// = Typedefs =====================================================================================

130
    typedef GenericProperty<bool> BoolProperty;
schultezub's avatar
schultezub committed
131
132
133
    typedef GenericProperty<std::string> StringProperty;

// = Template Implementation ======================================================================
schultezub's avatar
 
schultezub committed
134

schultezub's avatar
schultezub committed
135
    template<typename T>
136
137
    campvis::GenericProperty<T>::GenericProperty(const std::string& name, const std::string& title, const T& value, int invalidationLevel /*= AbstractProcessor::INVALID_RESULT*/) 
        : AbstractProperty(name, title, invalidationLevel)
schultezub's avatar
schultezub committed
138
        , _value(value)
139
        , _backBuffer(value)
schultezub's avatar
schultezub committed
140
141
    {
    }
schultezub's avatar
 
schultezub committed
142

schultezub's avatar
schultezub committed
143
    template<typename T>
schultezub's avatar
schultezub committed
144
    campvis::GenericProperty<T>::~GenericProperty() {
schultezub's avatar
 
schultezub committed
145

schultezub's avatar
schultezub committed
146
    }
schultezub's avatar
 
schultezub committed
147

148
    template<typename T>
schultezub's avatar
schultezub committed
149
    void campvis::GenericProperty<T>::addSharedProperty(AbstractProperty* prop) {
150
151
        // make type check first, then call base method.
        tgtAssert(prop != 0, "Shared property must not be 0!");
schultezub's avatar
schultezub committed
152
153
154
        if (GenericProperty<T>* tmp = dynamic_cast< GenericProperty<T>* >(prop)) {
            AbstractProperty::addSharedProperty(prop);
            tmp->setValue(getValue());
155
156
            return;
        }
schultezub's avatar
schultezub committed
157
        tgtAssert(false, "Shared property must be of the same type as this property!");
158
159
    }

schultezub's avatar
schultezub committed
160
    template<typename T>
schultezub's avatar
schultezub committed
161
    const T& campvis::GenericProperty<T>::getValue() const {
schultezub's avatar
schultezub committed
162
163
        return _value;
    }
schultezub's avatar
 
schultezub committed
164

schultezub's avatar
schultezub committed
165
    template<typename T>
schultezub's avatar
schultezub committed
166
    void campvis::GenericProperty<T>::setValue(const T& value) {
167
        T vv = validateValue(value);
schultezub's avatar
schultezub committed
168
        tbb::spin_mutex::scoped_lock lock(_localMutex);
169

170
        if (_inUse != 0)
171
            setBackValue(vv);
schultezub's avatar
schultezub committed
172
        else {
173
174
            setFrontValue(vv);
            setBackValue(vv);
schultezub's avatar
schultezub committed
175
        }
176
177
178
    }

    template<typename T>
schultezub's avatar
schultezub committed
179
    void campvis::GenericProperty<T>::unlock() {
schultezub's avatar
schultezub committed
180
        tbb::spin_mutex::scoped_lock lock(_localMutex);
181
182
183

        if (_backBuffer != _value)
            setFrontValue(_backBuffer);
184
        AbstractProperty::unlock();
185
186
187
    }

    template<typename T>
schultezub's avatar
schultezub committed
188
    void campvis::GenericProperty<T>::setFrontValue(const T& value) {
schultezub's avatar
schultezub committed
189
        _value = value;
190
191
192
193
194
195
196
197
        // TODO:    think about the correct/reasonable order of observer notification
        //          thread-safety might play a role thereby...
        for (std::set<AbstractProperty*>::iterator it = _sharedProperties.begin(); it != _sharedProperties.end(); ++it) {
            // We ensure all shared properties to be of type GenericProperty<T> in the addSharedProperty overload.
            // Hence, static_cast ist safe.
            GenericProperty<T>* child = static_cast< GenericProperty<T>* >(*it);
            child->setValue(value);
        }
schultezub's avatar
schultezub committed
198
        s_changed(this);
schultezub's avatar
schultezub committed
199
    }
schultezub's avatar
 
schultezub committed
200

201
    template<typename T>
schultezub's avatar
schultezub committed
202
    void campvis::GenericProperty<T>::setBackValue(const T& value) {
203
204
205
        _backBuffer = value;
    }

206
    template<typename T>
schultezub's avatar
schultezub committed
207
    T campvis::GenericProperty<T>::validateValue(const T& value) {
208
209
210
        return value;
    }

schultezub's avatar
schultezub committed
211
    template<typename T>
schultezub's avatar
schultezub committed
212
    const std::string campvis::GenericProperty<T>::loggerCat_ = "CAMPVis.core.datastructures.GenericProperty";
schultezub's avatar
 
schultezub committed
213
214
215
}

#endif // GENERICPROPERTY_H__