Lightmetrica  0.0.1.50dbee3 (yosakoi)
 All Classes Functions Variables Typedefs Enumerations Enumerator
component.h
1 /*
2  Lightmetrica : A research-oriented renderer
3 
4  Copyright (c) 2014 Hisanari Otsu
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #pragma once
21 #ifndef LIB_LIGHTMETRICA_COMPONENT_H
22 #define LIB_LIGHTMETRICA_COMPONENT_H
23 
24 #include "common.h"
25 #include "logger.h"
26 #include "align.h"
27 #include <string>
28 #include <functional>
29 #include <type_traits>
30 
31 LM_NAMESPACE_BEGIN
32 
45 class Component : public SIMDAlignedType
46 {
47 public:
48 
49  Component() {}
50  virtual ~Component() {}
51 
52 public:
53 
60  virtual std::string ComponentInterfaceTypeName() const = 0;
61 
68  virtual std::string ComponentImplTypeName() const = 0;
69 
70 };
71 
72 // --------------------------------------------------------------------------------
73 
79 class LM_PUBLIC_API ComponentFactory
80 {
81 public:
82 
83  typedef std::function<Component* ()> CreateComponentFunc;
84 
85 private:
86 
87  ComponentFactory() {}
88 
89 private:
90 
91  LM_DISABLE_COPY_AND_MOVE(ComponentFactory);
92 
93 public:
94 
102  static bool CheckRegistered(const std::string& interfaceType, const std::string& implType);
103 
114  static bool Register(const std::string& interfaceType, const std::string& implType, const CreateComponentFunc& func);
115 
122  static Component* Create(const std::string& interfaceType, const std::string& implType);
123 
129  static void LoadPlugins(const std::string& pluginDir);
130 
135  static void UnloadPlugins();
136 
137 
138 public:
139 
148  template <typename InterfaceType>
149  static bool CheckRegistered(const std::string& implType)
150  {
151  std::string interfaceType = InterfaceType::InterfaceTypeName();
152  return CheckRegistered(interfaceType, implType);
153  }
154 
162  template <typename InterfaceType>
163  static InterfaceType* Create(const std::string& implType)
164  {
165  std::string interfaceType = InterfaceType::InterfaceTypeName();
166 
167  auto* p1 = Create(interfaceType, implType);
168  if (p1 == nullptr)
169  {
170  LM_LOG_ERROR("Invalid instance type '" + implType + "' (interface type : '" + interfaceType + "')");
171  return nullptr;
172  }
173 
174  auto* p2 = dynamic_cast<InterfaceType*>(p1);
175  if (p2 == nullptr)
176  {
177  LM_LOG_ERROR("An instance of type '" + implType + "' is not inherited from '" + interfaceType + "'");
178  LM_SAFE_DELETE(p1);
179  return nullptr;
180  }
181 
182  return p2;
183  }
184 
191  template <typename InterfaceType>
192  static InterfaceType* Create()
193  {
194  return Create<InterfaceType>("default");
195  }
196 
197 };
198 
199 // --------------------------------------------------------------------------------
200 
209 template <typename ImplType, typename InterfaceType>
211 {
212 public:
213 
219  {
221  return instance;
222  }
223 
224 private:
225 
231  {
232  // Register entry here
233  if (!ComponentFactory::Register(InterfaceType::InterfaceTypeName(), ImplType::ImplTypeName(), [](){ return new ImplType; }))
234  {
235  LM_LOG_ERROR("Failed to register component '" + std::string(ImplType::ImplTypeName()) + "'");
236  }
237  }
238 
239 private:
240 
243  void operator=(const ComponentFactoryEntry<ImplType, InterfaceType>&);
245 
246 };
247 
248 LM_NAMESPACE_END
249 
250 // --------------------------------------------------------------------------------
251 
266 #define LM_COMPONENT_INTERFACE_DEF(Name) \
267  static const char* InterfaceTypeName() { return Name; } \
268  virtual std::string ComponentInterfaceTypeName() const { return InterfaceTypeName(); }
269 
270 #define LM_COMPONENT_IMPL_DEF(Name) \
271  static const char* ImplTypeName() { return Name; } \
272  virtual std::string ComponentImplTypeName() const { return ImplTypeName(); }
273 
274 // --------------------------------------------------------------------------------
275 
300 #define LM_COMPONENT_CREATE_HAS_MEMBER_FUNCTION(FuncName, Signature) \
301  template <typename T, typename = std::true_type> \
302  struct has_member_function_##FuncName : std::false_type {}; \
303  \
304  template <typename T> \
305  struct has_member_function_##FuncName< \
306  T, \
307  std::integral_constant< \
308  bool, \
309  check_func_signature<Signature, &T::FuncName>::value \
310  > \
311  > : std::true_type {}
312 
313 #define LM_COMPONENT_CHECK_HAS_MEMBER_FUNCTION(Type, FuncName) \
314  static_assert( \
315  has_member_function_##FuncName<Type>::value, \
316  "Component class of type '" #Type "' must have the member function '" #FuncName "'")
317 
318 #define LM_COMPONENT_CHECK_IS_DERIVED_CLASS(ImplType, InterfaceType) \
319  static_assert( \
320  std::is_base_of<InterfaceType, ImplType>::value, \
321  "Component class of type '" #ImplType "' must be inherited from the class of type '" #InterfaceType "'")
322 
323 // --------------------------------------------------------------------------------
324 
325 LM_NAMESPACE_BEGIN
326 
327 template <typename T, T>
328 struct check_func_signature : std::true_type {};
329 
330 LM_COMPONENT_CREATE_HAS_MEMBER_FUNCTION(ImplTypeName, const char* (*)());
331 LM_COMPONENT_CREATE_HAS_MEMBER_FUNCTION(InterfaceTypeName, const char* (*)());
332 
333 LM_NAMESPACE_END
334 
335 // --------------------------------------------------------------------------------
336 
348 #define LM_COMPONENT_REGISTER_IMPL(ImplType, InterfaceType) \
349  namespace { \
350  \
351  template <typename T1, typename T2> \
352  class ComponentFactoryEntryInstance; \
353  \
354  template <> \
355  class ComponentFactoryEntryInstance<ImplType, InterfaceType> \
356  { \
357  static const ::lightmetrica::ComponentFactoryEntry<ImplType, InterfaceType>& reg; \
358  }; \
359  \
360  const ::lightmetrica::ComponentFactoryEntry<ImplType, InterfaceType>& \
361  ComponentFactoryEntryInstance<ImplType, InterfaceType>::reg = \
362  ::lightmetrica::ComponentFactoryEntry<ImplType, InterfaceType>::Instance(); \
363  \
364  LM_COMPONENT_CHECK_IS_DERIVED_CLASS(ImplType, InterfaceType); \
365  LM_COMPONENT_CHECK_IS_DERIVED_CLASS(InterfaceType, Component); \
366  LM_COMPONENT_CHECK_HAS_MEMBER_FUNCTION(ImplType, ImplTypeName); \
367  LM_COMPONENT_CHECK_HAS_MEMBER_FUNCTION(InterfaceType, InterfaceTypeName); \
368  \
369  }
370 
371 #endif // LIB_LIGHTMETRICA_COMPONENT_H
static bool Register(const std::string &interfaceType, const std::string &implType, const CreateComponentFunc &func)
Definition: component.cpp:270
Definition: component.h:45
Definition: align.h:84
static InterfaceType * Create(const std::string &implType)
Definition: component.h:163
static bool CheckRegistered(const std::string &implType)
Definition: component.h:149
static ComponentFactoryEntry< ImplType, InterfaceType > & Instance()
Definition: component.h:218
Definition: component.h:210
static InterfaceType * Create()
Definition: component.h:192
Definition: component.h:79
virtual std::string ComponentInterfaceTypeName() const =0
Definition: component.h:328
virtual std::string ComponentImplTypeName() const =0