Delete SlowOperationInformer, which is no longer used.
[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     /// Node in linked list of entries.
81     ///
82     class node {
83       friend class iterator;
84
85       node *Next;
86       const entry& Val;
87
88     public:
89       node(const entry& V) : Next(0), Val(V) {
90         if (Tail)
91           Tail->Next = this;
92         else
93           Head = this;
94         Tail = this;
95
96         Announce(V);
97       }
98     };
99
100
101     /// Iterators for registry entries.
102     ///
103     class iterator {
104       const node *Cur;
105
106     public:
107       explicit iterator(const node *N) : Cur(N) {}
108
109       bool operator==(const iterator &That) const { return Cur == That.Cur; }
110       bool operator!=(const iterator &That) const { return Cur != That.Cur; }
111       iterator &operator++() { Cur = Cur->Next; return *this; }
112       const entry &operator*() const { return Cur->Val; }
113       const entry *operator->() const { return &Cur->Val; }
114     };
115
116     static iterator begin() { return iterator(Head); }
117     static iterator end()   { return iterator(0); }
118
119
120     /// Abstract base class for registry listeners, which are informed when new
121     /// entries are added to the registry. Simply subclass and instantiate:
122     ///
123     ///   class CollectorPrinter : public Registry<Collector>::listener {
124     ///   protected:
125     ///     void registered(const Registry<Collector>::entry &e) {
126     ///       cerr << "collector now available: " << e->getName() << "\n";
127     ///     }
128     ///
129     ///   public:
130     ///     CollectorPrinter() { init(); }  // Print those already registered.
131     ///   };
132     ///
133     ///   CollectorPrinter Printer;
134     ///
135     class listener {
136       listener *Prev, *Next;
137
138       friend void Registry::Announce(const entry &E);
139
140     protected:
141       /// Called when an entry is added to the registry.
142       ///
143       virtual void registered(const entry &) = 0;
144
145       /// Calls 'registered' for each pre-existing entry.
146       ///
147       void init() {
148         for (iterator I = begin(), E = end(); I != E; ++I)
149           registered(*I);
150       }
151
152     public:
153       listener() : Prev(ListenerTail), Next(0) {
154         if (Prev)
155           Prev->Next = this;
156         else
157           ListenerHead = this;
158         ListenerTail = this;
159       }
160
161       virtual ~listener() {
162         if (Next)
163           Next->Prev = Prev;
164         else
165           ListenerTail = Prev;
166         if (Prev)
167           Prev->Next = Next;
168         else
169           ListenerHead = Next;
170       }
171     };
172
173
174     /// A static registration template. Use like such:
175     ///
176     ///   Registry<Collector>::Add<FancyGC>
177     ///   X("fancy-gc", "Newfangled garbage collector.");
178     ///
179     /// Use of this template requires that:
180     ///
181     ///  1. The registered subclass has a default constructor.
182     //
183     ///  2. The registry entry type has a constructor compatible with this
184     ///     signature:
185     ///
186     ///       entry(const char *Name, const char *ShortDesc, T *(*Ctor)());
187     ///
188     /// If you have more elaborate requirements, then copy and modify.
189     ///
190     template <typename V>
191     class Add {
192       entry Entry;
193       node Node;
194
195       static T *CtorFn() { return new V(); }
196
197     public:
198       Add(const char *Name, const char *Desc)
199         : Entry(Name, Desc, CtorFn), Node(Entry) {}
200     };
201
202     /// Registry::Parser now lives in llvm/Support/RegistryParser.h.
203
204   };
205
206   // Since these are defined in a header file, plugins must be sure to export
207   // these symbols.
208
209   template <typename T, typename U>
210   typename Registry<T,U>::node *Registry<T,U>::Head;
211
212   template <typename T, typename U>
213   typename Registry<T,U>::node *Registry<T,U>::Tail;
214
215   template <typename T, typename U>
216   typename Registry<T,U>::listener *Registry<T,U>::ListenerHead;
217
218   template <typename T, typename U>
219   typename Registry<T,U>::listener *Registry<T,U>::ListenerTail;
220
221 }
222
223 #endif