Registry.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. //=== Registry.h - Linker-supported plugin registries -----------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // Defines a registry template for discovering pluggable modules.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_SUPPORT_REGISTRY_H
  14. #define LLVM_SUPPORT_REGISTRY_H
  15. #include "llvm/ADT/iterator_range.h"
  16. #include "llvm/ADT/STLExtras.h"
  17. #include "llvm/Support/Compiler.h"
  18. #include <memory>
  19. namespace llvm {
  20. /// A simple registry entry which provides only a name, description, and
  21. /// no-argument constructor.
  22. template <typename T>
  23. class SimpleRegistryEntry {
  24. const char *Name, *Desc;
  25. std::unique_ptr<T> (*Ctor)();
  26. public:
  27. SimpleRegistryEntry(const char *N, const char *D, std::unique_ptr<T> (*C)())
  28. : Name(N), Desc(D), Ctor(C)
  29. {}
  30. const char *getName() const { return Name; }
  31. const char *getDesc() const { return Desc; }
  32. std::unique_ptr<T> instantiate() const { return Ctor(); }
  33. };
  34. /// Traits for registry entries. If using other than SimpleRegistryEntry, it
  35. /// is necessary to define an alternate traits class.
  36. template <typename T>
  37. class RegistryTraits {
  38. RegistryTraits() = delete;
  39. public:
  40. typedef SimpleRegistryEntry<T> entry;
  41. /// nameof/descof - Accessors for name and description of entries. These are
  42. // used to generate help for command-line options.
  43. static const char *nameof(const entry &Entry) { return Entry.getName(); }
  44. static const char *descof(const entry &Entry) { return Entry.getDesc(); }
  45. };
  46. /// A global registry used in conjunction with static constructors to make
  47. /// pluggable components (like targets or garbage collectors) "just work" when
  48. /// linked with an executable.
  49. template <typename T, typename U = RegistryTraits<T> >
  50. class Registry {
  51. public:
  52. typedef U traits;
  53. typedef typename U::entry entry;
  54. class node;
  55. class listener;
  56. class iterator;
  57. private:
  58. Registry() = delete;
  59. static void Announce(const entry &E) {
  60. for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next)
  61. Cur->registered(E);
  62. }
  63. friend class node;
  64. static node *Head, *Tail;
  65. friend class listener;
  66. static listener *ListenerHead, *ListenerTail;
  67. public:
  68. /// Node in linked list of entries.
  69. ///
  70. class node {
  71. friend class iterator;
  72. node *Next;
  73. const entry& Val;
  74. public:
  75. node(const entry& V) : Next(nullptr), Val(V) {
  76. if (Tail)
  77. Tail->Next = this;
  78. else
  79. Head = this;
  80. Tail = this;
  81. Announce(V);
  82. }
  83. };
  84. /// Iterators for registry entries.
  85. ///
  86. class iterator {
  87. const node *Cur;
  88. public:
  89. explicit iterator(const node *N) : Cur(N) {}
  90. bool operator==(const iterator &That) const { return Cur == That.Cur; }
  91. bool operator!=(const iterator &That) const { return Cur != That.Cur; }
  92. iterator &operator++() { Cur = Cur->Next; return *this; }
  93. const entry &operator*() const { return Cur->Val; }
  94. const entry *operator->() const { return &Cur->Val; }
  95. };
  96. static iterator begin() { return iterator(Head); }
  97. static iterator end() { return iterator(nullptr); }
  98. static iterator_range<iterator> entries() {
  99. return iterator_range<iterator>(begin(), end());
  100. }
  101. /// Abstract base class for registry listeners, which are informed when new
  102. /// entries are added to the registry. Simply subclass and instantiate:
  103. ///
  104. /// \code
  105. /// class CollectorPrinter : public Registry<Collector>::listener {
  106. /// protected:
  107. /// void registered(const Registry<Collector>::entry &e) {
  108. /// cerr << "collector now available: " << e->getName() << "\n";
  109. /// }
  110. ///
  111. /// public:
  112. /// CollectorPrinter() { init(); } // Print those already registered.
  113. /// };
  114. ///
  115. /// CollectorPrinter Printer;
  116. /// \endcode
  117. class listener {
  118. listener *Prev, *Next;
  119. friend void Registry::Announce(const entry &E);
  120. protected:
  121. /// Called when an entry is added to the registry.
  122. ///
  123. virtual void registered(const entry &) = 0;
  124. /// Calls 'registered' for each pre-existing entry.
  125. ///
  126. void init() {
  127. for (iterator I = begin(), E = end(); I != E; ++I)
  128. registered(*I);
  129. }
  130. public:
  131. listener() : Prev(ListenerTail), Next(0) {
  132. if (Prev)
  133. Prev->Next = this;
  134. else
  135. ListenerHead = this;
  136. ListenerTail = this;
  137. }
  138. virtual ~listener() {
  139. if (Next)
  140. Next->Prev = Prev;
  141. else
  142. ListenerTail = Prev;
  143. if (Prev)
  144. Prev->Next = Next;
  145. else
  146. ListenerHead = Next;
  147. }
  148. };
  149. /// A static registration template. Use like such:
  150. ///
  151. /// Registry<Collector>::Add<FancyGC>
  152. /// X("fancy-gc", "Newfangled garbage collector.");
  153. ///
  154. /// Use of this template requires that:
  155. ///
  156. /// 1. The registered subclass has a default constructor.
  157. //
  158. /// 2. The registry entry type has a constructor compatible with this
  159. /// signature:
  160. ///
  161. /// entry(const char *Name, const char *ShortDesc, T *(*Ctor)());
  162. ///
  163. /// If you have more elaborate requirements, then copy and modify.
  164. ///
  165. template <typename V>
  166. class Add {
  167. entry Entry;
  168. node Node;
  169. static std::unique_ptr<T> CtorFn() { return make_unique<V>(); }
  170. public:
  171. Add(const char *Name, const char *Desc)
  172. : Entry(Name, Desc, CtorFn), Node(Entry) {}
  173. };
  174. /// Registry::Parser now lives in llvm/Support/RegistryParser.h.
  175. };
  176. // Since these are defined in a header file, plugins must be sure to export
  177. // these symbols.
  178. template <typename T, typename U>
  179. typename Registry<T,U>::node *Registry<T,U>::Head;
  180. template <typename T, typename U>
  181. typename Registry<T,U>::node *Registry<T,U>::Tail;
  182. template <typename T, typename U>
  183. typename Registry<T,U>::listener *Registry<T,U>::ListenerHead;
  184. template <typename T, typename U>
  185. typename Registry<T,U>::listener *Registry<T,U>::ListenerTail;
  186. }
  187. #endif