[Support/Registry.h] Include llvm/Support/Compiler.h.
[oota-llvm.git] / include / llvm / Support / Registry.h
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
14 #ifndef LLVM_SUPPORT_REGISTRY_H
15 #define LLVM_SUPPORT_REGISTRY_H
16
17 #include "llvm/Support/Compiler.h"
18
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     T *(*Ctor)();
26
27   public:
28     SimpleRegistryEntry(const char *N, const char *D, T *(*C)())
29       : Name(N), Desc(D), Ctor(C)
30     {}
31
32     const char *getName() const { return Name; }
33     const char *getDesc() const { return Desc; }
34     T *instantiate() const { return Ctor(); }
35   };
36
37
38   /// Traits for registry entries. If using other than SimpleRegistryEntry, it
39   /// is necessary to define an alternate traits class.
40   template <typename T>
41   class RegistryTraits {
42     RegistryTraits() LLVM_DELETED_FUNCTION;
43
44   public:
45     typedef SimpleRegistryEntry<T> entry;
46
47     /// nameof/descof - Accessors for name and description of entries. These are
48     //                  used to generate help for command-line options.
49     static const char *nameof(const entry &Entry) { return Entry.getName(); }
50     static const char *descof(const entry &Entry) { return Entry.getDesc(); }
51   };
52
53
54   /// A global registry used in conjunction with static constructors to make
55   /// pluggable components (like targets or garbage collectors) "just work" when
56   /// linked with an executable.
57   template <typename T, typename U = RegistryTraits<T> >
58   class Registry {
59   public:
60     typedef U traits;
61     typedef typename U::entry entry;
62
63     class node;
64     class listener;
65     class iterator;
66
67   private:
68     Registry() LLVM_DELETED_FUNCTION;
69
70     static void Announce(const entry &E) {
71       for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next)
72         Cur->registered(E);
73     }
74
75     friend class node;
76     static node *Head, *Tail;
77
78     friend class listener;
79     static listener *ListenerHead, *ListenerTail;
80
81   public:
82     /// Node in linked list of entries.
83     ///
84     class node {
85       friend class iterator;
86
87       node *Next;
88       const entry& Val;
89
90     public:
91       node(const entry& V) : Next(0), Val(V) {
92         if (Tail)
93           Tail->Next = this;
94         else
95           Head = this;
96         Tail = this;
97
98         Announce(V);
99       }
100     };
101
102
103     /// Iterators for registry entries.
104     ///
105     class iterator {
106       const node *Cur;
107
108     public:
109       explicit iterator(const node *N) : Cur(N) {}
110
111       bool operator==(const iterator &That) const { return Cur == That.Cur; }
112       bool operator!=(const iterator &That) const { return Cur != That.Cur; }
113       iterator &operator++() { Cur = Cur->Next; return *this; }
114       const entry &operator*() const { return Cur->Val; }
115       const entry *operator->() const { return &Cur->Val; }
116     };
117
118     static iterator begin() { return iterator(Head); }
119     static iterator end()   { return iterator(0); }
120
121
122     /// Abstract base class for registry listeners, which are informed when new
123     /// entries are added to the registry. Simply subclass and instantiate:
124     ///
125     /// \code
126     ///   class CollectorPrinter : public Registry<Collector>::listener {
127     ///   protected:
128     ///     void registered(const Registry<Collector>::entry &e) {
129     ///       cerr << "collector now available: " << e->getName() << "\n";
130     ///     }
131     ///
132     ///   public:
133     ///     CollectorPrinter() { init(); }  // Print those already registered.
134     ///   };
135     ///
136     ///   CollectorPrinter Printer;
137     /// \endcode
138     class listener {
139       listener *Prev, *Next;
140
141       friend void Registry::Announce(const entry &E);
142
143     protected:
144       /// Called when an entry is added to the registry.
145       ///
146       virtual void registered(const entry &) = 0;
147
148       /// Calls 'registered' for each pre-existing entry.
149       ///
150       void init() {
151         for (iterator I = begin(), E = end(); I != E; ++I)
152           registered(*I);
153       }
154
155     public:
156       listener() : Prev(ListenerTail), Next(0) {
157         if (Prev)
158           Prev->Next = this;
159         else
160           ListenerHead = this;
161         ListenerTail = this;
162       }
163
164       virtual ~listener() {
165         if (Next)
166           Next->Prev = Prev;
167         else
168           ListenerTail = Prev;
169         if (Prev)
170           Prev->Next = Next;
171         else
172           ListenerHead = Next;
173       }
174     };
175
176
177     /// A static registration template. Use like such:
178     ///
179     ///   Registry<Collector>::Add<FancyGC>
180     ///   X("fancy-gc", "Newfangled garbage collector.");
181     ///
182     /// Use of this template requires that:
183     ///
184     ///  1. The registered subclass has a default constructor.
185     //
186     ///  2. The registry entry type has a constructor compatible with this
187     ///     signature:
188     ///
189     ///       entry(const char *Name, const char *ShortDesc, T *(*Ctor)());
190     ///
191     /// If you have more elaborate requirements, then copy and modify.
192     ///
193     template <typename V>
194     class Add {
195       entry Entry;
196       node Node;
197
198       static T *CtorFn() { return new V(); }
199
200     public:
201       Add(const char *Name, const char *Desc)
202         : Entry(Name, Desc, CtorFn), Node(Entry) {}
203     };
204
205     /// Registry::Parser now lives in llvm/Support/RegistryParser.h.
206
207   };
208
209   // Since these are defined in a header file, plugins must be sure to export
210   // these symbols.
211
212   template <typename T, typename U>
213   typename Registry<T,U>::node *Registry<T,U>::Head;
214
215   template <typename T, typename U>
216   typename Registry<T,U>::node *Registry<T,U>::Tail;
217
218   template <typename T, typename U>
219   typename Registry<T,U>::listener *Registry<T,U>::ListenerHead;
220
221   template <typename T, typename U>
222   typename Registry<T,U>::listener *Registry<T,U>::ListenerTail;
223
224 }
225
226 #endif