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() LLVM_DELETED_FUNCTION;
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() LLVM_DELETED_FUNCTION;
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     /// Node in linked list of entries.
00081     ///
00082     class node {
00083       friend class iterator;
00084 
00085       node *Next;
00086       const entry& Val;
00087 
00088     public:
00089       node(const entry& V) : Next(0), Val(V) {
00090         if (Tail)
00091           Tail->Next = this;
00092         else
00093           Head = this;
00094         Tail = this;
00095 
00096         Announce(V);
00097       }
00098     };
00099 
00100 
00101     /// Iterators for registry entries.
00102     ///
00103     class iterator {
00104       const node *Cur;
00105 
00106     public:
00107       explicit iterator(const node *N) : Cur(N) {}
00108 
00109       bool operator==(const iterator &That) const { return Cur == That.Cur; }
00110       bool operator!=(const iterator &That) const { return Cur != That.Cur; }
00111       iterator &operator++() { Cur = Cur->Next; return *this; }
00112       const entry &operator*() const { return Cur->Val; }
00113       const entry *operator->() const { return &Cur->Val; }
00114     };
00115 
00116     static iterator begin() { return iterator(Head); }
00117     static iterator end()   { return iterator(0); }
00118 
00119 
00120     /// Abstract base class for registry listeners, which are informed when new
00121     /// entries are added to the registry. Simply subclass and instantiate:
00122     ///
00123     /// \code
00124     ///   class CollectorPrinter : public Registry<Collector>::listener {
00125     ///   protected:
00126     ///     void registered(const Registry<Collector>::entry &e) {
00127     ///       cerr << "collector now available: " << e->getName() << "\n";
00128     ///     }
00129     ///
00130     ///   public:
00131     ///     CollectorPrinter() { init(); }  // Print those already registered.
00132     ///   };
00133     ///
00134     ///   CollectorPrinter Printer;
00135     /// \endcode
00136     class listener {
00137       listener *Prev, *Next;
00138 
00139       friend void Registry::Announce(const entry &E);
00140 
00141     protected:
00142       /// Called when an entry is added to the registry.
00143       ///
00144       virtual void registered(const entry &) = 0;
00145 
00146       /// Calls 'registered' for each pre-existing entry.
00147       ///
00148       void init() {
00149         for (iterator I = begin(), E = end(); I != E; ++I)
00150           registered(*I);
00151       }
00152 
00153     public:
00154       listener() : Prev(ListenerTail), Next(0) {
00155         if (Prev)
00156           Prev->Next = this;
00157         else
00158           ListenerHead = this;
00159         ListenerTail = this;
00160       }
00161 
00162       virtual ~listener() {
00163         if (Next)
00164           Next->Prev = Prev;
00165         else
00166           ListenerTail = Prev;
00167         if (Prev)
00168           Prev->Next = Next;
00169         else
00170           ListenerHead = Next;
00171       }
00172     };
00173 
00174 
00175     /// A static registration template. Use like such:
00176     ///
00177     ///   Registry<Collector>::Add<FancyGC>
00178     ///   X("fancy-gc", "Newfangled garbage collector.");
00179     ///
00180     /// Use of this template requires that:
00181     ///
00182     ///  1. The registered subclass has a default constructor.
00183     //
00184     ///  2. The registry entry type has a constructor compatible with this
00185     ///     signature:
00186     ///
00187     ///       entry(const char *Name, const char *ShortDesc, T *(*Ctor)());
00188     ///
00189     /// If you have more elaborate requirements, then copy and modify.
00190     ///
00191     template <typename V>
00192     class Add {
00193       entry Entry;
00194       node Node;
00195 
00196       static T *CtorFn() { return new V(); }
00197 
00198     public:
00199       Add(const char *Name, const char *Desc)
00200         : Entry(Name, Desc, CtorFn), Node(Entry) {}
00201     };
00202 
00203     /// Registry::Parser now lives in llvm/Support/RegistryParser.h.
00204 
00205   };
00206 
00207   // Since these are defined in a header file, plugins must be sure to export
00208   // these symbols.
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