Home | History | Annotate | Download | only in Support
      1 //===-- llvm/Support/ManagedStatic.h - Static Global wrapper ----*- 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 // This file defines the ManagedStatic class and the llvm_shutdown() function.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_SUPPORT_MANAGEDSTATIC_H
     15 #define LLVM_SUPPORT_MANAGEDSTATIC_H
     16 
     17 #include <atomic>
     18 #include <cstddef>
     19 
     20 namespace llvm {
     21 
     22 /// object_creator - Helper method for ManagedStatic.
     23 template <class C> struct object_creator {
     24   static void *call() { return new C(); }
     25 };
     26 
     27 /// object_deleter - Helper method for ManagedStatic.
     28 ///
     29 template <typename T> struct object_deleter {
     30   static void call(void *Ptr) { delete (T *)Ptr; }
     31 };
     32 template <typename T, size_t N> struct object_deleter<T[N]> {
     33   static void call(void *Ptr) { delete[](T *)Ptr; }
     34 };
     35 
     36 /// ManagedStaticBase - Common base class for ManagedStatic instances.
     37 class ManagedStaticBase {
     38 protected:
     39   // This should only be used as a static variable, which guarantees that this
     40   // will be zero initialized.
     41   mutable std::atomic<void *> Ptr;
     42   mutable void (*DeleterFn)(void*);
     43   mutable const ManagedStaticBase *Next;
     44 
     45   void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const;
     46 
     47 public:
     48   /// isConstructed - Return true if this object has not been created yet.
     49   bool isConstructed() const { return Ptr != nullptr; }
     50 
     51   void destroy() const;
     52 };
     53 
     54 /// ManagedStatic - This transparently changes the behavior of global statics to
     55 /// be lazily constructed on demand (good for reducing startup times of dynamic
     56 /// libraries that link in LLVM components) and for making destruction be
     57 /// explicit through the llvm_shutdown() function call.
     58 ///
     59 template <class C, class Creator = object_creator<C>,
     60           class Deleter = object_deleter<C>>
     61 class ManagedStatic : public ManagedStaticBase {
     62 public:
     63   // Accessors.
     64   C &operator*() {
     65     void *Tmp = Ptr.load(std::memory_order_acquire);
     66     if (!Tmp)
     67       RegisterManagedStatic(Creator::call, Deleter::call);
     68 
     69     return *static_cast<C *>(Ptr.load(std::memory_order_relaxed));
     70   }
     71 
     72   C *operator->() { return &**this; }
     73 
     74   const C &operator*() const {
     75     void *Tmp = Ptr.load(std::memory_order_acquire);
     76     if (!Tmp)
     77       RegisterManagedStatic(Creator::call, Deleter::call);
     78 
     79     return *static_cast<C *>(Ptr.load(std::memory_order_relaxed));
     80   }
     81 
     82   const C *operator->() const { return &**this; }
     83 };
     84 
     85 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
     86 void llvm_shutdown();
     87 
     88 /// llvm_shutdown_obj - This is a simple helper class that calls
     89 /// llvm_shutdown() when it is destroyed.
     90 struct llvm_shutdown_obj {
     91   llvm_shutdown_obj() = default;
     92   ~llvm_shutdown_obj() { llvm_shutdown(); }
     93 };
     94 
     95 } // end namespace llvm
     96 
     97 #endif // LLVM_SUPPORT_MANAGEDSTATIC_H
     98