datacontainer.h 7.18 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
// 
// ================================================================================================

schultezub's avatar
schultezub committed
25
26
#ifndef DATACONTAINER_H__
#define DATACONTAINER_H__
schultezub's avatar
schultezub committed
27

schultezub's avatar
schultezub committed
28
#include "sigslot/sigslot.h"
29
30
#include <tbb/concurrent_unordered_map.h>
#include <tbb/spin_mutex.h>
31
32

#include "core/coreapi.h"
schultezub's avatar
schultezub committed
33
#include "core/datastructures/datahandle.h"
schultezub's avatar
schultezub committed
34
35
36

#include <string>
#include <map>
37
38
#include <utility>
#include <vector>
schultezub's avatar
schultezub committed
39

schultezub's avatar
schultezub committed
40
namespace campvis {
schultezub's avatar
schultezub committed
41
42
    class AbstractData;
    
schultezub's avatar
schultezub committed
43
44
45
46
    /**
     * A DataContainer manages instances of AbstractData and offers access to them via string identifiers (names/keys).
     * Therefore, it stores them in DataHandles which take ownership of the AbstractData instance. Hence,
     * as soon as an AbstractData instance is added to a DataContainer via DataContainer::addData(), its 
47
     * lifetime is managed by the wrapping DataHandle instance and its reference counting mechanism.
schultezub's avatar
schultezub committed
48
     * Because the DataHandles are stored as const handles, the underlying data cannot be changed anymore. This
49
     * also ensures (hopefully) that nobody can do messy things, such as changing the data while some other 
50
51
     * thread is reading it. Theoretically this should be possible, but a correct implementation would require
     * some brain fuck.
schultezub's avatar
schultezub committed
52
     * 
53
     * \todo    Check thread-safety
schultezub's avatar
schultezub committed
54
     */
55
    class CAMPVIS_CORE_API DataContainer {
schultezub's avatar
schultezub committed
56
57
58
    public:
        /**
         * Creates a new empty DataContainer
59
         * \param   name    The name of the new DataContainer
schultezub's avatar
schultezub committed
60
         */
61
        DataContainer(const std::string& name);
schultezub's avatar
schultezub committed
62
63
64
65
66
67
68
69
70
71

        /**
         * Destructor of the DataContainer. Will disconnect all DataHandles from this container.
         */
        ~DataContainer();


        /**
         * Adds the given AbstractData instance \a data, accessible by the key \name, to this DataContainer.
         * In doing so, the DataContainer (respectively the created DataHandle) takes ownership of \a data
schultezub's avatar
schultezub committed
72
         * and will manage its lifetime. So don't even think about deleting \a data yourself!
schultezub's avatar
schultezub committed
73
         *
74
75
         * \param   name    Key for accessing the DataHandle within this DataContainer.
         * \param   data    The data to wrap in a DataHandle and add to this DataContainer, must not be 0.
76
         * \return  A DataHandle containing \a data.
schultezub's avatar
schultezub committed
77
         */
78
        DataHandle addData(const std::string& name, AbstractData* data);
schultezub's avatar
schultezub committed
79
80
81
82
83
84
85
86

        /**
         * Adds the given DataHandle \a data, accessible by the key \name, to this DataContainer.
         * Already existing DataHandles with the same key will be removed from this DataContainer.
         *
         * \param   name    Key for accessing the DataHandle within this DataContainer
         * \param   data    DataHandle to add.
         */
87
        void addDataHandle(const std::string& name, const DataHandle& dh);
schultezub's avatar
schultezub committed
88
89
90
91
92
93
94
95
96
97
98

        /**
         * Checks whether this DataContainer contains a DataHandle with the given name.
         *
         * \param   name    Key of the DataHandle to search for
         * \return  true, if this DataContainer contains a DataHandle with the given name.
         */
        bool hasData(const std::string& name) const;

        /**
         * Returns the DataHandle with the given name from this container.
99
         * If no such DataHandle exists, this method returns an empty DataHandle.
schultezub's avatar
schultezub committed
100
101
         *
         * \param   name    Key of the DataHandle to search for
102
         * \return  The stored DataHandle with the given name, an empty DataHandle if no such DataHandle exists.
schultezub's avatar
schultezub committed
103
         */
104
        DataHandle getData(const std::string& name) const;
schultezub's avatar
schultezub committed
105

schultezub's avatar
schultezub committed
106
107
108
109
110
111
        /**
         * Removes the DataHandle with the given name from this container.
         * If no such DataHandle exists, nothing happens.
         * \param   name    Key of the DataHandle to remove.
         */
        void removeData(const std::string& name);
schultezub's avatar
schultezub committed
112

113
114
115
116
117
118
        /**
         * Removes all DataHandles from this DataContainer.
         * \note    This method is \b NOT thread-safe!
         */
        void clear();

119
120
121
122
123
124
        /**
         * Returns a copy of the current list of DataHandles.
         * \note    Use with caution, this method is to be considered as slow, as it includes several 
         *          copies and locks the whole DataContainer during execution.
         * \return  A list of pairs (name, DataHandle). The caller has to take ownership of the passed pointers!
         */
125
        std::vector< std::pair< std::string, DataHandle> > getDataHandlesCopy() const;
126

127
128
129
130
131
132
133
134
135
136
137
138
        /**
         * Returns the name of this DataContainer.
         * \return  _name
         */
        const std::string& getName() const;

        /**
         * Sets the name of this DataContainer.
         * \param   name    The new name of this DataContainer
         */
        void setName(const std::string& name);

139
140
141
142
143
144
        /**
         * Returns a copy of the current map of DataHandles.
         * \note    Use with caution, this method is to be considered as slow, as it includes several 
         *          copies and locks the whole DataContainer during execution.
         * \return  A copy of the current handles map. The caller has to take ownership of the passed pointers!
         */
145
        //std::map<std::string, DataHandle> getHandlesCopy() const;
146

schultezub's avatar
schultezub committed
147
148
149
150
        /**
         * Signal emitted when data has been added to this DataContainer (this includes also data being replaced).
         * First parameter is the name of the added data, second parameter contains a DataHandle to the new data.
         */
151
        sigslot::signal2<const std::string&, const DataHandle&> s_dataAdded;
schultezub's avatar
schultezub committed
152

153
154
155
        /// Signal emitted when list of DataHandles has changed.
        sigslot::signal0<> s_changed;

schultezub's avatar
schultezub committed
156
    private:
157
        /// Map of the DataHandles in this collection and their IDs. The DataHandles contain valid data.
158
        //std::map<std::string, DataHandle> _handles;
159
        mutable tbb::spin_mutex _localMutex;
schultezub's avatar
schultezub committed
160

161
162
        tbb::concurrent_unordered_map<std::string, DataHandle> _handles;

163
164
        std::string _name;

schultezub's avatar
schultezub committed
165
166
167
168
        static const std::string loggerCat_;
    };

}
schultezub's avatar
schultezub committed
169
170

#endif // DATACONTAINER_H__