Registry.h should not depend on CommandLine.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 namespace llvm {
18   /// A simple registry entry which provides only a name, description, and
19   /// no-argument constructor.
20   template <typename T>
21   class SimpleRegistryEntry {
22     const char *Name, *Desc;
23     T *(*Ctor)();
24
25   public:
26     SimpleRegistryEntry(const char *N, const char *D, T *(*C)())
27       : Name(N), Desc(D), Ctor(C)
28     {}
29
30     const char *getName() const { return Name; }
31     const char *getDesc() const { return Desc; }
32     T *instantiate() const { return Ctor(); }
33   };
34
35
36   /// Traits for registry entries. If using other than SimpleRegistryEntry, it
37   /// is necessary to define an alternate traits class.
38   template <typename T>
39   class RegistryTraits {
40     RegistryTraits(); // Do not implement.
41
42   public:
43     typedef SimpleRegistryEntry<T> entry;
44
45     /// nameof/descof - Accessors for name and description of entries. These are
46     //                  used to generate help for command-line options.
47     static const char *nameof(const entry &Entry) { return Entry.getName(); }
48     static const char *descof(const entry &Entry) { return Entry.getDesc(); }
49   };
50
51
52   /// A global registry used in conjunction with static constructors to make
53   /// pluggable components (like targets or garbage collectors) "just work" when
54   /// linked with an executable.
55   template <typename T, typename U = RegistryTraits<T> >
56   class Registry {
57   public:
58     typedef U traits;
59     typedef typename U::entry entry;
60
61     class node;
62     class listener;
63     class iterator;
64
65   private:
66     Registry(); // Do not implement.
67
68     static void Announce(const entry &E) {
69       for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next)
70         Cur->registered(E);
71     }
72
73     friend class node;
74     static node *Head, *Tail;
75
76     friend class listener;
77     static listener *ListenerHead, *ListenerTail;
78
79   public:
80     class iterator;
81
82
83     /// Node in linked list of entries.
84     ///
85     class node {
86       friend class iterator;
87
88       node *Next;
89       const entry& Val;
90
91     public:
92       node(const entry& V) : Next(0), Val(V) {
93         if (Tail)
94           Tail->Next = this;
95         else
96           Head = this;
97         Tail = this;
98
99         Announce(V);
100       }
101     };
102
103
104     /// Iterators for registry entries.
105     ///
106     class iterator {
107       const node *Cur;
108
109     public:
110       explicit iterator(const node *N) : Cur(N) {}
111
112       bool operator==(const iterator &That) const { return Cur == That.Cur; }
113       bool operator!=(const iterator &That) const { return Cur != That.Cur; }
114       iterator &operator++() { Cur = Cur->Next; return *this; }
115       const entry &operator*() const { return Cur->Val; }
116       const entry *operator->() const { return &Cur->Val; }
117     };
118
119     static iterator begin() { return iterator(Head); }
120     static iterator end()   { return iterator(0); }
121
122
123     /// Abstract base class for registry listeners, which are informed when new
124     /// entries are added to the registry. Simply subclass and instantiate:
125     ///
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     ///
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
210   template <typename T, typename U>
211   typename Registry<T,U>::node *Registry<T,U>::Head;
212
213   template <typename T, typename U>
214   typename Registry<T,U>::node *Registry<T,U>::Tail;
215
216   template <typename T, typename U>
217   typename Registry<T,U>::listener *Registry<T,U>::ListenerHead;
218
219   template <typename T, typename U>
220   typename Registry<T,U>::listener *Registry<T,U>::ListenerTail;
221
222 }
223
224 #endif