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
20namespace llvm {
21
22/// object_creator - Helper method for ManagedStatic.
23template <class C> struct object_creator {
24 static void *call() { return new C(); }
25};
26
27/// object_deleter - Helper method for ManagedStatic.
28///
29template <typename T> struct object_deleter {
30 static void call(void *Ptr) { delete (T *)Ptr; }
31};
32template <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.
37class ManagedStaticBase {
38protected:
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
47public:
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///
59template <class C, class Creator = object_creator<C>,
60 class Deleter = object_deleter<C>>
61class ManagedStatic : public ManagedStaticBase {
62public:
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.
86void llvm_shutdown();
87
88/// llvm_shutdown_obj - This is a simple helper class that calls
89/// llvm_shutdown() when it is destroyed.
90struct 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