processorfactory.h 5.69 KB
Newer Older
Hossain Mahmud's avatar
Hossain Mahmud committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// ================================================================================================
// 
// This file is part of the CAMPVis Software Framework.
// 
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
//      Chair for Computer Aided Medical Procedures
//      Technische Universitaet Muenchen
//      Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
// 
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
// 
// 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
// 
// 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.
// 
// ================================================================================================

#ifndef PROCESSORFACTORY_H__
#define PROCESSORFACTORY_H__

#include "cgt/logmanager.h"
#include "cgt/singleton.h"

#include <tbb/atomic.h>
#include <tbb/spin_mutex.h>

#include "modules/modulesapi.h"

#include <map>
#include <string>
#include <vector>
#include <functional>
Hossain Mahmud's avatar
Hossain Mahmud committed
40
#include "core/properties/numericproperty.h"
Hossain Mahmud's avatar
Hossain Mahmud committed
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

namespace campvis {
    class AbstractProcessor;
    class DataContainer;

    /**
     * Factory for creating processors by their name.
     * Using some template-magic, ProcessorFactory is able to register processors during static 
     * initialization in cooperation with the ProcessorRegistrar.
     * 
     * \note    ProcessorFactory is a thread-safe lazy-instantiated singleton.
     */
    class CAMPVIS_MODULES_API ProcessorFactory {
    public:
        /**
         * Returns a reference to the ProcessorFactory singleton.
         * Creates the singleton if necessary
         * \return  *_singleton
         */
        static ProcessorFactory& getRef();
    
        static void deinit();
        
        std::vector<std::string> getRegisteredProcessors() const;

66
        AbstractProcessor* createProcessor(const std::string& id, IVec2Property* viewPortSizeProp = 0) const;
Hossain Mahmud's avatar
Hossain Mahmud committed
67
68
69
70
71
72
73

        /**
         * Statically registers the processor of type T using \a callee as factory method.
         * \note    The template instantiation of ProcessorRegistrar takes care of calling this method.
         * \param   callee  Factory method to call to create an instance of type T
         * \return  The registration index.
         */
Hossain Mahmud's avatar
Hossain Mahmud committed
74
        template<typename T>
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
        size_t registerProcessor2(std::function<AbstractProcessor*(IVec2Property*)> callee) {
            tbb::spin_mutex::scoped_lock lock(_mutex);

            auto it = _processorMap2.lower_bound(T::getId());
            if (it == _processorMap2.end() || it->first != T::getId()) {
                _processorMap2.insert(it, std::make_pair(T::getId(), callee));
            }
            else {
                cgtAssert(false, "Registered two processors with the same ID.");
            }

            return _processorMap2.size();
        }

        template<typename T>
        size_t registerProcessor(std::function<AbstractProcessor*()> callee) {
Hossain Mahmud's avatar
Hossain Mahmud committed
91
92
93
94
            tbb::spin_mutex::scoped_lock lock(_mutex);

            auto it = _processorMap.lower_bound(T::getId());
            if (it == _processorMap.end() || it->first != T::getId()) {
Hossain Mahmud's avatar
Hossain Mahmud committed
95
                _processorMap.insert(it, std::make_pair(T::getId(), callee));
Hossain Mahmud's avatar
Hossain Mahmud committed
96
97
98
99
            }
            else {
                cgtAssert(false, "Registered two processors with the same ID.");
            }
Hossain Mahmud's avatar
Hossain Mahmud committed
100

Hossain Mahmud's avatar
Hossain Mahmud committed
101
102
103
104
105
106
            return _processorMap.size();
        }
    private:
        mutable tbb::spin_mutex _mutex;
        static tbb::atomic<ProcessorFactory*> _singleton;    ///< the singleton object

107
108
        std::map< std::string, std::function<AbstractProcessor*()>> _processorMap;
        std::map< std::string, std::function<AbstractProcessor*(IVec2Property*)>> _processorMap2;
Hossain Mahmud's avatar
Hossain Mahmud committed
109
110
111
112
113
    };


// ================================================================================================

Hossain Mahmud's avatar
Hossain Mahmud committed
114
    template<typename T>
Hossain Mahmud's avatar
Hossain Mahmud committed
115
116
117
118
119
120
    class ProcessorRegistrar {
    public:
        /**
         * Static factory method for creating the processor of type T.
         * \return  A newly created processor of type T. Caller has to take ownership of the pointer.
         */
121
122
123
        static AbstractProcessor* create() {
            return new T();
        }
Hossain Mahmud's avatar
Hossain Mahmud committed
124

125
126
127
128
129
130
131
132
133
134
135
136
137
    private:
        /// static helper field to ensure registration at static initialization time.
        static const size_t _factoryId;
    };
    
    template<typename T>
    class ProcessorRegistrar2 {
    public:
        /**
         * Static factory method for creating the processor of type T.
         * \param   viewPortSizeProp  viewPortSizeProp for the created processor to work on.
         * \return  A newly created processor of type T. Caller has to take ownership of the pointer.
         */
Hossain Mahmud's avatar
Hossain Mahmud committed
138
139
        static AbstractProcessor* create(IVec2Property* viewPortSizeProp) {
            return new T(viewPortSizeProp);
Hossain Mahmud's avatar
Hossain Mahmud committed
140
141
142
143
144
145
146
        }

    private:
        /// static helper field to ensure registration at static initialization time.
        static const size_t _factoryId;
    };

Hossain Mahmud's avatar
Hossain Mahmud committed
147
148
    template<typename T>
    const size_t ProcessorRegistrar<T>::_factoryId = ProcessorFactory::getRef().registerProcessor<T>(&ProcessorRegistrar<T>::create);
149
150
    template<typename T>
    const size_t ProcessorRegistrar2<T>::_factoryId = ProcessorFactory::getRef().registerProcessor2<T>(&ProcessorRegistrar2<T>::create);
Hossain Mahmud's avatar
Hossain Mahmud committed
151
152
153
154

}

#endif // PROCESSORFACTORY_H__