Mark unimplemented copy constructors and copy assignment operators as LLVM_DELETED_FU...
[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() LLVM_DELETED_FUNCTION;
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() LLVM_DELETED_FUNCTION;
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     /// \code
124     ///   class CollectorPrinter : public Registry<Collector>::listener {
125     ///   protected:
126     ///     void registered(const Registry<Collector>::entry &e) {
127     ///       cerr << "collector now available: " << e->getName() << "\n";
128     ///     }
129     ///
130     ///   public:
131     ///     CollectorPrinter() { init(); }  // Print those already registered.
132     ///   };
133     ///
134     ///   CollectorPrinter Printer;
135     /// \endcode
136     class listener {
137       listener *Prev, *Next;
138
139       friend void Registry::Announce(const entry &E);
140
141     protected:
142       /// Called when an entry is added to the registry.
143       ///
144       virtual void registered(const entry &) = 0;
145
146       /// Calls 'registered' for each pre-existing entry.
147       ///
148       void init() {
149         for (iterator I = begin(), E = end(); I != E; ++I)
150           registered(*I);
151       }
152
153     public:
154       listener() : Prev(ListenerTail), Next(0) {
155         if (Prev)
156           Prev->Next = this;
157         else
158           ListenerHead = this;
159         ListenerTail = this;
160       }
161
162       virtual ~listener() {
163         if (Next)
164           Next->Prev = Prev;
165         else
166           ListenerTail = Prev;
167         if (Prev)
168           Prev->Next = Next;
169         else
170           ListenerHead = Next;
171       }
172     };
173
174
175     /// A static registration template. Use like such:
176     ///
177     ///   Registry<Collector>::Add<FancyGC>
178     ///   X("fancy-gc", "Newfangled garbage collector.");
179     ///
180     /// Use of this template requires that:
181     ///
182     ///  1. The registered subclass has a default constructor.
183     //
184     ///  2. The registry entry type has a constructor compatible with this
185     ///     signature:
186     ///
187     ///       entry(const char *Name, const char *ShortDesc, T *(*Ctor)());
188     ///
189     /// If you have more elaborate requirements, then copy and modify.
190     ///
191     template <typename V>
192     class Add {
193       entry Entry;
194       node Node;
195
196       static T *CtorFn() { return new V(); }
197
198     public:
199       Add(const char *Name, const char *Desc)
200         : Entry(Name, Desc, CtorFn), Node(Entry) {}
201     };
202
203     /// Registry::Parser now lives in llvm/Support/RegistryParser.h.
204
205   };
206
207   // Since these are defined in a header file, plugins must be sure to export
208   // these symbols.
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