LLVM API Documentation

ManagedStatic.h
Go to the documentation of this file.
00001 //===-- llvm/Support/ManagedStatic.h - Static Global wrapper ----*- 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 // This file defines the ManagedStatic class and the llvm_shutdown() function.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_SUPPORT_MANAGEDSTATIC_H
00015 #define LLVM_SUPPORT_MANAGEDSTATIC_H
00016 
00017 #include "llvm/Support/Atomic.h"
00018 #include "llvm/Support/Threading.h"
00019 #include "llvm/Support/Valgrind.h"
00020 
00021 namespace llvm {
00022 
00023 /// object_creator - Helper method for ManagedStatic.
00024 template<class C>
00025 void* object_creator() {
00026   return new C();
00027 }
00028 
00029 /// object_deleter - Helper method for ManagedStatic.
00030 ///
00031 template<typename T> struct object_deleter {
00032   static void call(void * Ptr) { delete (T*)Ptr; }
00033 };
00034 template<typename T, size_t N> struct object_deleter<T[N]> {
00035   static void call(void * Ptr) { delete[] (T*)Ptr; }
00036 };
00037 
00038 /// ManagedStaticBase - Common base class for ManagedStatic instances.
00039 class ManagedStaticBase {
00040 protected:
00041   // This should only be used as a static variable, which guarantees that this
00042   // will be zero initialized.
00043   mutable void *Ptr;
00044   mutable void (*DeleterFn)(void*);
00045   mutable const ManagedStaticBase *Next;
00046 
00047   void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const;
00048 public:
00049   /// isConstructed - Return true if this object has not been created yet.
00050   bool isConstructed() const { return Ptr != nullptr; }
00051 
00052   void destroy() const;
00053 };
00054 
00055 /// ManagedStatic - This transparently changes the behavior of global statics to
00056 /// be lazily constructed on demand (good for reducing startup times of dynamic
00057 /// libraries that link in LLVM components) and for making destruction be
00058 /// explicit through the llvm_shutdown() function call.
00059 ///
00060 template<class C>
00061 class ManagedStatic : public ManagedStaticBase {
00062 public:
00063 
00064   // Accessors.
00065   C &operator*() {
00066     void* tmp = Ptr;
00067     if (llvm_is_multithreaded()) sys::MemoryFence();
00068     if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
00069     TsanHappensAfter(this);
00070 
00071     return *static_cast<C*>(Ptr);
00072   }
00073   C *operator->() {
00074     void* tmp = Ptr;
00075     if (llvm_is_multithreaded()) sys::MemoryFence();
00076     if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
00077     TsanHappensAfter(this);
00078 
00079     return static_cast<C*>(Ptr);
00080   }
00081   const C &operator*() const {
00082     void* tmp = Ptr;
00083     if (llvm_is_multithreaded()) sys::MemoryFence();
00084     if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
00085     TsanHappensAfter(this);
00086 
00087     return *static_cast<C*>(Ptr);
00088   }
00089   const C *operator->() const {
00090     void* tmp = Ptr;
00091     if (llvm_is_multithreaded()) sys::MemoryFence();
00092     if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
00093     TsanHappensAfter(this);
00094 
00095     return static_cast<C*>(Ptr);
00096   }
00097 };
00098 
00099 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
00100 void llvm_shutdown();
00101 
00102 /// llvm_shutdown_obj - This is a simple helper class that calls
00103 /// llvm_shutdown() when it is destroyed.
00104 struct llvm_shutdown_obj {
00105   llvm_shutdown_obj() { }
00106   ~llvm_shutdown_obj() { llvm_shutdown(); }
00107 };
00108 
00109 }
00110 
00111 #endif