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 {
callobject_creator24   static void *call() { return new C(); }
25 };
26 
27 /// object_deleter - Helper method for ManagedStatic.
28 ///
29 template <typename T> struct object_deleter {
callobject_deleter30   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