LLVM API Documentation

Registry.h

Go to the documentation of this file.
00001 //=== Registry.h - Linker-supported plugin registries -----------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // Defines a registry template for discovering pluggable modules.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_SUPPORT_REGISTRY_H
00015 #define LLVM_SUPPORT_REGISTRY_H
00016 
00017 namespace llvm {
00018   /// A simple registry entry which provides only a name, description, and
00019   /// no-argument constructor.
00020   template <typename T>
00021   class SimpleRegistryEntry {
00022     const char *Name, *Desc;
00023     T *(*Ctor)();
00024 
00025   public:
00026     SimpleRegistryEntry(const char *N, const char *D, T *(*C)())
00027       : Name(N), Desc(D), Ctor(C)
00028     {}
00029 
00030     const char *getName() const { return Name; }
00031     const char *getDesc() const { return Desc; }
00032     T *instantiate() const { return Ctor(); }
00033   };
00034 
00035 
00036   /// Traits for registry entries. If using other than SimpleRegistryEntry, it
00037   /// is necessary to define an alternate traits class.
00038   template <typename T>
00039   class RegistryTraits {
00040     RegistryTraits(); // Do not implement.
00041 
00042   public:
00043     typedef SimpleRegistryEntry<T> entry;
00044 
00045     /// nameof/descof - Accessors for name and description of entries. These are
00046     //                  used to generate help for command-line options.
00047     static const char *nameof(const entry &Entry) { return Entry.getName(); }
00048     static const char *descof(const entry &Entry) { return Entry.getDesc(); }
00049   };
00050 
00051 
00052   /// A global registry used in conjunction with static constructors to make
00053   /// pluggable components (like targets or garbage collectors) "just work" when
00054   /// linked with an executable.
00055   template <typename T, typename U = RegistryTraits<T> >
00056   class Registry {
00057   public:
00058     typedef U traits;
00059     typedef typename U::entry entry;
00060 
00061     class node;
00062     class listener;
00063     class iterator;
00064 
00065   private:
00066     Registry(); // Do not implement.
00067 
00068     static void Announce(const entry &E) {
00069       for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next)
00070         Cur->registered(E);
00071     }
00072 
00073     friend class node;
00074     static node *Head, *Tail;
00075 
00076     friend class listener;
00077     static listener *ListenerHead, *ListenerTail;
00078 
00079   public:
00080     class iterator;
00081 
00082 
00083     /// Node in linked list of entries.
00084     ///
00085     class node {
00086       friend class iterator;
00087 
00088       node *Next;
00089       const entry& Val;
00090 
00091     public:
00092       node(const entry& V) : Next(0), Val(V) {
00093         if (Tail)
00094           Tail->Next = this;
00095         else
00096           Head = this;
00097         Tail = this;
00098 
00099         Announce(V);
00100       }
00101     };
00102 
00103 
00104     /// Iterators for registry entries.
00105     ///
00106     class iterator {
00107       const node *Cur;
00108 
00109     public:
00110       explicit iterator(const node *N) : Cur(N) {}
00111 
00112       bool operator==(const iterator &That) const { return Cur == That.Cur; }
00113       bool operator!=(const iterator &That) const { return Cur != That.Cur; }
00114       iterator &operator++() { Cur = Cur->Next; return *this; }
00115       const entry &operator*() const { return Cur->Val; }
00116       const entry *operator->() const { return &Cur->Val; }
00117     };
00118 
00119     static iterator begin() { return iterator(Head); }
00120     static iterator end()   { return iterator(0); }
00121 
00122 
00123     /// Abstract base class for registry listeners, which are informed when new
00124     /// entries are added to the registry. Simply subclass and instantiate:
00125     ///
00126     ///   class CollectorPrinter : public Registry<Collector>::listener {
00127     ///   protected:
00128     ///     void registered(const Registry<Collector>::entry &e) {
00129     ///       cerr << "collector now available: " << e->getName() << "\n";
00130     ///     }
00131     ///
00132     ///   public:
00133     ///     CollectorPrinter() { init(); }  // Print those already registered.
00134     ///   };
00135     ///
00136     ///   CollectorPrinter Printer;
00137     ///
00138     class listener {
00139       listener *Prev, *Next;
00140 
00141       friend void Registry::Announce(const entry &E);
00142 
00143     protected:
00144       /// Called when an entry is added to the registry.
00145       ///
00146       virtual void registered(const entry &) = 0;
00147 
00148       /// Calls 'registered' for each pre-existing entry.
00149       ///
00150       void init() {
00151         for (iterator I = begin(), E = end(); I != E; ++I)
00152           registered(*I);
00153       }
00154 
00155     public:
00156       listener() : Prev(ListenerTail), Next(0) {
00157         if (Prev)
00158           Prev->Next = this;
00159         else
00160           ListenerHead = this;
00161         ListenerTail = this;
00162       }
00163 
00164       virtual ~listener() {
00165         if (Next)
00166           Next->Prev = Prev;
00167         else
00168           ListenerTail = Prev;
00169         if (Prev)
00170           Prev->Next = Next;
00171         else
00172           ListenerHead = Next;
00173       }
00174     };
00175 
00176 
00177     /// A static registration template. Use like such:
00178     ///
00179     ///   Registry<Collector>::Add<FancyGC>
00180     ///   X("fancy-gc", "Newfangled garbage collector.");
00181     ///
00182     /// Use of this template requires that:
00183     ///
00184     ///  1. The registered subclass has a default constructor.
00185     //
00186     ///  2. The registry entry type has a constructor compatible with this
00187     ///     signature:
00188     ///
00189     ///       entry(const char *Name, const char *ShortDesc, T *(*Ctor)());
00190     ///
00191     /// If you have more elaborate requirements, then copy and modify.
00192     ///
00193     template <typename V>
00194     class Add {
00195       entry Entry;
00196       node Node;
00197 
00198       static T *CtorFn() { return new V(); }
00199 
00200     public:
00201       Add(const char *Name, const char *Desc)
00202         : Entry(Name, Desc, CtorFn), Node(Entry) {}
00203     };
00204 
00205     /// Registry::Parser now lives in llvm/Support/RegistryParser.h.
00206 
00207   };
00208 
00209 
00210   template <typename T, typename U>
00211   typename Registry<T,U>::node *Registry<T,U>::Head;
00212 
00213   template <typename T, typename U>
00214   typename Registry<T,U>::node *Registry<T,U>::Tail;
00215 
00216   template <typename T, typename U>
00217   typename Registry<T,U>::listener *Registry<T,U>::ListenerHead;
00218 
00219   template <typename T, typename U>
00220   typename Registry<T,U>::listener *Registry<T,U>::ListenerTail;
00221 
00222 }
00223 
00224 #endif