1 | // |
2 | // MetaObject.h |
3 | // |
4 | // Library: Foundation |
5 | // Package: SharedLibrary |
6 | // Module: ClassLoader |
7 | // |
8 | // Definition of the MetaObject class. |
9 | // |
10 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
11 | // and Contributors. |
12 | // |
13 | // SPDX-License-Identifier: BSL-1.0 |
14 | // |
15 | |
16 | |
17 | #ifndef Foundation_MetaObject_INCLUDED |
18 | #define Foundation_MetaObject_INCLUDED |
19 | |
20 | |
21 | #include "Poco/Foundation.h" |
22 | #include "Poco/Exception.h" |
23 | #include "Poco/SingletonHolder.h" |
24 | #include <set> |
25 | |
26 | |
27 | namespace Poco { |
28 | |
29 | |
30 | template <class B> |
31 | class AbstractMetaObject |
32 | /// A MetaObject stores some information |
33 | /// about a C++ class. The MetaObject class |
34 | /// is used by the Manifest class. |
35 | /// AbstractMetaObject is a common base class |
36 | /// for all MetaObject in a rooted class hierarchy. |
37 | /// A MetaObject can also be used as an object |
38 | /// factory for its class. |
39 | { |
40 | public: |
41 | AbstractMetaObject(const char* pName): _name(pName) |
42 | { |
43 | } |
44 | |
45 | virtual ~AbstractMetaObject() |
46 | { |
47 | for (typename ObjectSet::iterator it = _deleteSet.begin(); it != _deleteSet.end(); ++it) |
48 | { |
49 | delete *it; |
50 | } |
51 | } |
52 | |
53 | const char* name() const |
54 | { |
55 | return _name; |
56 | } |
57 | |
58 | virtual B* create() const = 0; |
59 | /// Create a new instance of a class. |
60 | /// Cannot be used for singletons. |
61 | |
62 | virtual B& instance() const = 0; |
63 | /// Returns a reference to the only instance |
64 | /// of the class. Used for singletons only. |
65 | |
66 | virtual bool canCreate() const = 0; |
67 | /// Returns true iff the create method can be used |
68 | /// to create instances of the class. |
69 | /// Returns false if the class is a singleton. |
70 | |
71 | virtual void destroy(B* pObject) const |
72 | /// If pObject was owned by meta object, the |
73 | /// ownership of the deleted object is removed |
74 | /// and the object is deleted. |
75 | { |
76 | typename ObjectSet::iterator it = _deleteSet.find(pObject); |
77 | |
78 | if (it != _deleteSet.end()) |
79 | { |
80 | _deleteSet.erase(pObject); |
81 | delete pObject; |
82 | } |
83 | } |
84 | |
85 | B* autoDelete(B* pObject) const |
86 | /// Give ownership of pObject to the meta object. |
87 | /// The meta object will delete all objects it owns |
88 | /// when it is destroyed. |
89 | /// |
90 | /// Returns pObject. |
91 | { |
92 | if (this->canCreate()) // guard against singleton |
93 | { |
94 | poco_check_ptr (pObject); |
95 | _deleteSet.insert(pObject); |
96 | } |
97 | else throw InvalidAccessException("Cannot take ownership of" , this->name()); |
98 | |
99 | return pObject; |
100 | } |
101 | |
102 | virtual bool isAutoDelete(B* pObject) const |
103 | /// Returns true if the object is owned |
104 | /// by meta object. |
105 | /// |
106 | /// Overloaded in MetaSingleton - returns true |
107 | /// if the class is a singleton. |
108 | { |
109 | return _deleteSet.find(pObject) != _deleteSet.end(); |
110 | } |
111 | |
112 | private: |
113 | AbstractMetaObject(); |
114 | AbstractMetaObject(const AbstractMetaObject&); |
115 | AbstractMetaObject& operator = (const AbstractMetaObject&); |
116 | |
117 | typedef std::set<B*> ObjectSet; |
118 | |
119 | const char* _name; |
120 | mutable ObjectSet _deleteSet; |
121 | }; |
122 | |
123 | |
124 | template <class C, class B> |
125 | class MetaObject: public AbstractMetaObject<B> |
126 | /// A MetaObject stores some information |
127 | /// about a C++ class. The MetaObject class |
128 | /// is used by the Manifest class. |
129 | /// A MetaObject can also be used as an object |
130 | /// factory for its class. |
131 | { |
132 | public: |
133 | MetaObject(const char* name): AbstractMetaObject<B>(name) |
134 | { |
135 | } |
136 | |
137 | ~MetaObject() |
138 | { |
139 | } |
140 | |
141 | B* create() const |
142 | { |
143 | return new C; |
144 | } |
145 | |
146 | B& instance() const |
147 | { |
148 | throw InvalidAccessException("Not a singleton. Use create() to create instances of" , this->name()); |
149 | } |
150 | |
151 | bool canCreate() const |
152 | { |
153 | return true; |
154 | } |
155 | }; |
156 | |
157 | |
158 | template <class C, class B> |
159 | class MetaSingleton: public AbstractMetaObject<B> |
160 | /// A SingletonMetaObject disables the create() method |
161 | /// and instead offers an instance() method to access |
162 | /// the single instance of its class. |
163 | { |
164 | public: |
165 | MetaSingleton(const char* name): AbstractMetaObject<B>(name) |
166 | { |
167 | } |
168 | |
169 | ~MetaSingleton() |
170 | { |
171 | } |
172 | |
173 | B* create() const |
174 | { |
175 | throw InvalidAccessException("Cannot create instances of a singleton class. Use instance() to obtain a" , this->name()); |
176 | } |
177 | |
178 | bool canCreate() const |
179 | { |
180 | return false; |
181 | } |
182 | |
183 | B& instance() const |
184 | { |
185 | return *_object.get(); |
186 | } |
187 | |
188 | bool isAutoDelete(B* /*pObject*/) const |
189 | { |
190 | return true; |
191 | } |
192 | |
193 | private: |
194 | mutable SingletonHolder<C> _object; |
195 | }; |
196 | |
197 | |
198 | } // namespace Poco |
199 | |
200 | |
201 | #endif // Foundation_MetaObject_INCLUDED |
202 | |