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_MANAGED_STATIC_H
     15 #define LLVM_SUPPORT_MANAGED_STATIC_H
     16 
     17 #include "llvm/Support/Atomic.h"
     18 #include "llvm/Support/Threading.h"
     19 
     20 namespace llvm {
     21 
     22 /// object_creator - Helper method for ManagedStatic.
     23 template<class C>
     24 void* object_creator() {
     25   return new C();
     26 }
     27 
     28 /// object_deleter - Helper method for ManagedStatic.
     29 ///
     30 template<typename T> struct object_deleter {
     31   static void call(void * Ptr) { delete (T*)Ptr; }
     32 };
     33 template<typename T, size_t N> struct object_deleter<T[N]> {
     34   static void call(void * Ptr) { delete[] (T*)Ptr; }
     35 };
     36 
     37 /// ManagedStaticBase - Common base class for ManagedStatic instances.
     38 class ManagedStaticBase {
     39 protected:
     40   // This should only be used as a static variable, which guarantees that this
     41   // will be zero initialized.
     42   mutable void *Ptr;
     43   mutable void (*DeleterFn)(void*);
     44   mutable const ManagedStaticBase *Next;
     45 
     46   void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const;
     47 public:
     48   /// isConstructed - Return true if this object has not been created yet.
     49   bool isConstructed() const { return Ptr != 0; }
     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>
     60 class ManagedStatic : public ManagedStaticBase {
     61 public:
     62 
     63   // Accessors.
     64   C &operator*() {
     65     void* tmp = Ptr;
     66     if (llvm_is_multithreaded()) sys::MemoryFence();
     67     if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
     68 
     69     return *static_cast<C*>(Ptr);
     70   }
     71   C *operator->() {
     72     void* tmp = Ptr;
     73     if (llvm_is_multithreaded()) sys::MemoryFence();
     74     if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
     75 
     76     return static_cast<C*>(Ptr);
     77   }
     78   const C &operator*() const {
     79     void* tmp = Ptr;
     80     if (llvm_is_multithreaded()) sys::MemoryFence();
     81     if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
     82 
     83     return *static_cast<C*>(Ptr);
     84   }
     85   const C *operator->() const {
     86     void* tmp = Ptr;
     87     if (llvm_is_multithreaded()) sys::MemoryFence();
     88     if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
     89 
     90     return static_cast<C*>(Ptr);
     91   }
     92 };
     93 
     94 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
     95 void llvm_shutdown();
     96 
     97 
     98 /// llvm_shutdown_obj - This is a simple helper class that calls
     99 /// llvm_shutdown() when it is destroyed.
    100 struct llvm_shutdown_obj {
    101   llvm_shutdown_obj() { }
    102   explicit llvm_shutdown_obj(bool multithreaded) {
    103     if (multithreaded) llvm_start_multithreaded();
    104   }
    105   ~llvm_shutdown_obj() { llvm_shutdown(); }
    106 };
    107 
    108 }
    109 
    110 #endif
    111