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 "llvm/Support/Compiler.h" 18 #include <atomic> 19 #include <cstddef> 20 21 namespace llvm { 22 23 /// object_creator - Helper method for ManagedStatic. 24 template<class C> object_creator()25LLVM_LIBRARY_VISIBILITY void* object_creator() { 26 return new C(); 27 } 28 29 /// object_deleter - Helper method for ManagedStatic. 30 /// 31 template <typename T> struct LLVM_LIBRARY_VISIBILITY object_deleter { callobject_deleter32 static void call(void *Ptr) { delete (T *)Ptr; } 33 }; 34 template <typename T, size_t N> 35 struct LLVM_LIBRARY_VISIBILITY object_deleter<T[N]> { 36 static void call(void *Ptr) { delete[](T *)Ptr; } 37 }; 38 39 // If the current compiler is MSVC 2017 or earlier, then we have to work around 40 // a bug where MSVC emits code to perform dynamic initialization even if the 41 // class has a constexpr constructor. Instead, fall back to the C++98 strategy 42 // where there are no constructors or member initializers. We can remove this 43 // when MSVC 2019 (19.20+) is our minimum supported version. 44 #if !defined(__clang__) && defined(_MSC_VER) && _MSC_VER < 1920 45 #define LLVM_AVOID_CONSTEXPR_CTOR 46 #endif 47 48 /// ManagedStaticBase - Common base class for ManagedStatic instances. 49 class ManagedStaticBase { 50 protected: 51 #ifndef LLVM_AVOID_CONSTEXPR_CTOR 52 mutable std::atomic<void *> Ptr{}; 53 mutable void (*DeleterFn)(void *) = nullptr; 54 mutable const ManagedStaticBase *Next = nullptr; 55 #else 56 // This should only be used as a static variable, which guarantees that this 57 // will be zero initialized. 58 mutable std::atomic<void *> Ptr; 59 mutable void (*DeleterFn)(void *); 60 mutable const ManagedStaticBase *Next; 61 #endif 62 63 void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const; 64 65 public: 66 #ifndef LLVM_AVOID_CONSTEXPR_CTOR 67 constexpr ManagedStaticBase() = default; 68 #endif 69 70 /// isConstructed - Return true if this object has not been created yet. 71 bool isConstructed() const { return Ptr != nullptr; } 72 73 void destroy() const; 74 }; 75 76 /// ManagedStatic - This transparently changes the behavior of global statics to 77 /// be lazily constructed on demand (good for reducing startup times of dynamic 78 /// libraries that link in LLVM components) and for making destruction be 79 /// explicit through the llvm_shutdown() function call. 80 /// 81 template<class C> 82 class ManagedStatic : public ManagedStaticBase { 83 public: 84 // Accessors. 85 C &operator*() { 86 void *Tmp = Ptr.load(std::memory_order_acquire); 87 if (!Tmp) 88 RegisterManagedStatic(object_creator<C>, object_deleter<C>::call); 89 90 return *static_cast<C *>(Ptr.load(std::memory_order_relaxed)); 91 } 92 93 C *operator->() { return &**this; } 94 95 const C &operator*() const { 96 void *Tmp = Ptr.load(std::memory_order_acquire); 97 if (!Tmp) 98 RegisterManagedStatic(object_creator<C>, object_deleter<C>::call); 99 100 return *static_cast<C *>(Ptr.load(std::memory_order_relaxed)); 101 } 102 103 const C *operator->() const { return &**this; } 104 }; 105 106 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. 107 void llvm_shutdown(); 108 109 /// llvm_shutdown_obj - This is a simple helper class that calls 110 /// llvm_shutdown() when it is destroyed. 111 struct llvm_shutdown_obj { 112 llvm_shutdown_obj() = default; 113 ~llvm_shutdown_obj() { llvm_shutdown(); } 114 }; 115 116 } // end namespace llvm 117 118 #endif // LLVM_SUPPORT_MANAGEDSTATIC_H 119