registry.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /* Copyright 2016 Google Inc. All Rights Reserved.
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. ==============================================================================*/
  12. // Registry for component registration. These classes can be used for creating
  13. // registries of components conforming to the same interface. This is useful for
  14. // making a component-based architecture where the specific implementation
  15. // classes can be selected at runtime. There is support for both class-based and
  16. // instance based registries.
  17. //
  18. // Example:
  19. // function.h:
  20. //
  21. // class Function : public RegisterableInstance<Function> {
  22. // public:
  23. // virtual double Evaluate(double x) = 0;
  24. // };
  25. //
  26. // #define REGISTER_FUNCTION(type, component)
  27. // REGISTER_INSTANCE_COMPONENT(Function, type, component);
  28. //
  29. // function.cc:
  30. //
  31. // REGISTER_INSTANCE_REGISTRY("function", Function);
  32. //
  33. // class Cos : public Function {
  34. // public:
  35. // double Evaluate(double x) { return cos(x); }
  36. // };
  37. //
  38. // class Exp : public Function {
  39. // public:
  40. // double Evaluate(double x) { return exp(x); }
  41. // };
  42. //
  43. // REGISTER_FUNCTION("cos", Cos);
  44. // REGISTER_FUNCTION("exp", Exp);
  45. //
  46. // Function *f = Function::Lookup("cos");
  47. // double result = f->Evaluate(arg);
  48. #ifndef SYNTAXNET_REGISTRY_H_
  49. #define SYNTAXNET_REGISTRY_H_
  50. #include <string.h>
  51. #include <string>
  52. #include <vector>
  53. #include "syntaxnet/utils.h"
  54. namespace syntaxnet {
  55. // Component metadata with information about name, class, and code location.
  56. class ComponentMetadata {
  57. public:
  58. ComponentMetadata(const char *name, const char *class_name, const char *file,
  59. int line)
  60. : name_(name),
  61. class_name_(class_name),
  62. file_(file),
  63. line_(line),
  64. link_(nullptr) {}
  65. // Returns component name.
  66. const char *name() const { return name_; }
  67. // Metadata objects can be linked in a list.
  68. ComponentMetadata *link() const { return link_; }
  69. void set_link(ComponentMetadata *link) { link_ = link; }
  70. private:
  71. // Component name.
  72. const char *name_;
  73. // Name of class for component.
  74. const char *class_name_;
  75. // Code file and location where the component was registered.
  76. const char *file_;
  77. int line_;
  78. // Link to next metadata object in list.
  79. ComponentMetadata *link_;
  80. };
  81. // The master registry contains all registered component registries. A registry
  82. // is not registered in the master registry until the first component of that
  83. // type is registered.
  84. class RegistryMetadata : public ComponentMetadata {
  85. public:
  86. RegistryMetadata(const char *name, const char *class_name, const char *file,
  87. int line, ComponentMetadata **components)
  88. : ComponentMetadata(name, class_name, file, line),
  89. components_(components) {}
  90. // Registers a component registry in the master registry.
  91. static void Register(RegistryMetadata *registry);
  92. private:
  93. // Location of list of components in registry.
  94. ComponentMetadata **components_;
  95. };
  96. // Registry for components. An object can be registered with a type name in the
  97. // registry. The named instances in the registry can be returned using the
  98. // Lookup() method. The components in the registry are put into a linked list
  99. // of components. It is important that the component registry can be statically
  100. // initialized in order not to depend on initialization order.
  101. template <class T>
  102. struct ComponentRegistry {
  103. typedef ComponentRegistry<T> Self;
  104. // Component registration class.
  105. class Registrar : public ComponentMetadata {
  106. public:
  107. // Registers new component by linking itself into the component list of
  108. // the registry.
  109. Registrar(Self *registry, const char *type, const char *class_name,
  110. const char *file, int line, T *object)
  111. : ComponentMetadata(type, class_name, file, line), object_(object) {
  112. // Register registry in master registry if this is the first registered
  113. // component of this type.
  114. if (registry->components == nullptr) {
  115. RegistryMetadata::Register(new RegistryMetadata(
  116. registry->name, registry->class_name, registry->file,
  117. registry->line,
  118. reinterpret_cast<ComponentMetadata **>(&registry->components)));
  119. }
  120. // Register component in registry.
  121. set_link(registry->components);
  122. registry->components = this;
  123. }
  124. // Returns component type.
  125. const char *type() const { return name(); }
  126. // Returns component object.
  127. T *object() const { return object_; }
  128. // Returns the next component in the component list.
  129. Registrar *next() const { return static_cast<Registrar *>(link()); }
  130. private:
  131. // Component object.
  132. T *object_;
  133. };
  134. // Finds registrar for named component in registry.
  135. const Registrar *GetComponent(const char *type) const {
  136. Registrar *r = components;
  137. while (r != nullptr && strcmp(type, r->type()) != 0) r = r->next();
  138. if (r == nullptr) {
  139. LOG(FATAL) << "Unknown " << name << " component: '" << type << "'.";
  140. }
  141. return r;
  142. }
  143. // Finds a named component in the registry.
  144. T *Lookup(const char *type) const { return GetComponent(type)->object(); }
  145. T *Lookup(const string &type) const { return Lookup(type.c_str()); }
  146. // Textual description of the kind of components in the registry.
  147. const char *name;
  148. // Base class name of component type.
  149. const char *class_name;
  150. // File and line where the registry is defined.
  151. const char *file;
  152. int line;
  153. // Linked list of registered components.
  154. Registrar *components;
  155. };
  156. // Base class for registerable class-based components.
  157. template <class T>
  158. class RegisterableClass {
  159. public:
  160. // Factory function type.
  161. typedef T *(Factory)();
  162. // Registry type.
  163. typedef ComponentRegistry<Factory> Registry;
  164. // Creates a new component instance.
  165. static T *Create(const string &type) { return registry()->Lookup(type)(); }
  166. // Returns registry for class.
  167. static Registry *registry() { return &registry_; }
  168. private:
  169. // Registry for class.
  170. static Registry registry_;
  171. };
  172. // Base class for registerable instance-based components.
  173. template <class T>
  174. class RegisterableInstance {
  175. public:
  176. // Registry type.
  177. typedef ComponentRegistry<T> Registry;
  178. private:
  179. // Registry for class.
  180. static Registry registry_;
  181. };
  182. #define REGISTER_CLASS_COMPONENT(base, type, component) \
  183. static base *__##component##__factory() { return new component; } \
  184. static base::Registry::Registrar __##component##__##registrar( \
  185. base::registry(), type, #component, __FILE__, __LINE__, \
  186. __##component##__factory)
  187. #define REGISTER_CLASS_REGISTRY(type, classname) \
  188. template <> \
  189. classname::Registry RegisterableClass<classname>::registry_ = { \
  190. type, #classname, __FILE__, __LINE__, NULL}
  191. #define REGISTER_INSTANCE_COMPONENT(base, type, component) \
  192. static base::Registry::Registrar __##component##__##registrar( \
  193. base::registry(), type, #component, __FILE__, __LINE__, new component)
  194. #define REGISTER_INSTANCE_REGISTRY(type, classname) \
  195. template <> \
  196. classname::Registry RegisterableInstance<classname>::registry_ = { \
  197. type, #classname, __FILE__, __LINE__, NULL}
  198. } // namespace syntaxnet
  199. #endif // SYNTAXNET_REGISTRY_H_