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 #include "llvm/Support/Valgrind.h"
     20 
     21 namespace llvm {
     22 
     23 /// object_creator - Helper method for ManagedStatic.
     24 template<class C>
     25 void* object_creator() {
     26   return new C();
     27 }
     28 
     29 /// object_deleter - Helper method for ManagedStatic.
     30 ///
     31 template<typename T> struct object_deleter {
     32   static void call(void * Ptr) { delete (T*)Ptr; }
     33 };
     34 template<typename T, size_t N> struct object_deleter<T[N]> {
     35   static void call(void * Ptr) { delete[] (T*)Ptr; }
     36 };
     37 
     38 /// ManagedStaticBase - Common base class for ManagedStatic instances.
     39 class ManagedStaticBase {
     40 protected:
     41   // This should only be used as a static variable, which guarantees that this
     42   // will be zero initialized.
     43   mutable void *Ptr;
     44   mutable void (*DeleterFn)(void*);
     45   mutable const ManagedStaticBase *Next;
     46 
     47   void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const;
     48 public:
     49   /// isConstructed - Return true if this object has not been created yet.
     50   bool isConstructed() const { return Ptr != nullptr; }
     51 
     52   void destroy() const;
     53 };
     54 
     55 /// ManagedStatic - This transparently changes the behavior of global statics to
     56 /// be lazily constructed on demand (good for reducing startup times of dynamic
     57 /// libraries that link in LLVM components) and for making destruction be
     58 /// explicit through the llvm_shutdown() function call.
     59 ///
     60 template<class C>
     61 class ManagedStatic : public ManagedStaticBase {
     62 public:
     63 
     64   // Accessors.
     65   C &operator*() {
     66     void* tmp = Ptr;
     67     if (llvm_is_multithreaded()) sys::MemoryFence();
     68     if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
     69     TsanHappensAfter(this);
     70 
     71     return *static_cast<C*>(Ptr);
     72   }
     73   C *operator->() {
     74     void* tmp = Ptr;
     75     if (llvm_is_multithreaded()) sys::MemoryFence();
     76     if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
     77     TsanHappensAfter(this);
     78 
     79     return static_cast<C*>(Ptr);
     80   }
     81   const C &operator*() const {
     82     void* tmp = Ptr;
     83     if (llvm_is_multithreaded()) sys::MemoryFence();
     84     if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
     85     TsanHappensAfter(this);
     86 
     87     return *static_cast<C*>(Ptr);
     88   }
     89   const C *operator->() const {
     90     void* tmp = Ptr;
     91     if (llvm_is_multithreaded()) sys::MemoryFence();
     92     if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
     93     TsanHappensAfter(this);
     94 
     95     return static_cast<C*>(Ptr);
     96   }
     97 };
     98 
     99 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
    100 void llvm_shutdown();
    101 
    102 /// llvm_shutdown_obj - This is a simple helper class that calls
    103 /// llvm_shutdown() when it is destroyed.
    104 struct llvm_shutdown_obj {
    105   llvm_shutdown_obj() { }
    106   ~llvm_shutdown_obj() { llvm_shutdown(); }
    107 };
    108 
    109 }
    110 
    111 #endif
    112