LLVM 22.0.0git
ManagedStatic.h
Go to the documentation of this file.
1//===-- llvm/Support/ManagedStatic.h - Static Global wrapper ----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the ManagedStatic class and the llvm_shutdown() function.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_SUPPORT_MANAGEDSTATIC_H
14#define LLVM_SUPPORT_MANAGEDSTATIC_H
15
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// ManagedStatic must be initialized to zero, and it must *not* have a dynamic
37// initializer because managed statics are often created while running other
38// dynamic initializers. In standard C++11, the best way to accomplish this is
39// with a constexpr default constructor. However, different versions of the
40// Visual C++ compiler have had bugs where, even though the constructor may be
41// constexpr, a dynamic initializer may be emitted depending on optimization
42// settings. For the affected versions of MSVC, use the old linker
43// initialization pattern of not providing a constructor and leaving the fields
44// uninitialized. See http://llvm.org/PR41367 for details.
45#if !defined(_MSC_VER) || (_MSC_VER >= 1925) || defined(__clang__)
46#define LLVM_USE_CONSTEXPR_CTOR
47#endif
48
49/// ManagedStaticBase - Common base class for ManagedStatic instances.
51protected:
52#ifdef LLVM_USE_CONSTEXPR_CTOR
53 mutable std::atomic<void *> Ptr{};
54 mutable void (*DeleterFn)(void *) = nullptr;
55 mutable const ManagedStaticBase *Next = nullptr;
56#else
57 // This should only be used as a static variable, which guarantees that this
58 // will be zero initialized.
59 mutable std::atomic<void *> Ptr;
60 mutable void (*DeleterFn)(void *);
61 mutable const ManagedStaticBase *Next;
62#endif
63
64 LLVM_ABI void RegisterManagedStatic(void *(*creator)(),
65 void (*deleter)(void *)) const;
66
67public:
68#ifdef LLVM_USE_CONSTEXPR_CTOR
69 constexpr ManagedStaticBase() = default;
70#endif
71
72 /// isConstructed - Return true if this object has not been created yet.
73 bool isConstructed() const { return Ptr != nullptr; }
74
75 LLVM_ABI void destroy() const;
76};
77
78/// ManagedStatic - This transparently changes the behavior of global statics to
79/// be lazily constructed on demand (good for reducing startup times of dynamic
80/// libraries that link in LLVM components) and for making destruction be
81/// explicit through the llvm_shutdown() function call.
82///
83template <class C, class Creator = object_creator<C>,
84 class Deleter = object_deleter<C>>
86public:
87 // Accessors.
89 void *Tmp = Ptr.load(std::memory_order_acquire);
90 if (!Tmp)
91 RegisterManagedStatic(Creator::call, Deleter::call);
92
93 return *static_cast<C *>(Ptr.load(std::memory_order_relaxed));
94 }
95
96 C *operator->() { return &**this; }
97
98 const C &operator*() const {
99 void *Tmp = Ptr.load(std::memory_order_acquire);
100 if (!Tmp)
101 RegisterManagedStatic(Creator::call, Deleter::call);
102
103 return *static_cast<C *>(Ptr.load(std::memory_order_relaxed));
104 }
105
106 const C *operator->() const { return &**this; }
107
108 // Extract the instance, leaving the ManagedStatic uninitialized. The
109 // user is then responsible for the lifetime of the returned instance.
110 C *claim() {
111 return static_cast<C *>(Ptr.exchange(nullptr));
112 }
113};
114
115/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
117
118/// llvm_shutdown_obj - This is a simple helper class that calls
119/// llvm_shutdown() when it is destroyed.
121 llvm_shutdown_obj() = default;
123};
124
125} // end namespace llvm
126
127#endif // LLVM_SUPPORT_MANAGEDSTATIC_H
#define LLVM_ABI
Definition: Compiler.h:213
ManagedStaticBase - Common base class for ManagedStatic instances.
Definition: ManagedStatic.h:50
LLVM_ABI void RegisterManagedStatic(void *(*creator)(), void(*deleter)(void *)) const
constexpr ManagedStaticBase()=default
void(* DeleterFn)(void *)
Definition: ManagedStatic.h:54
const ManagedStaticBase * Next
Definition: ManagedStatic.h:55
std::atomic< void * > Ptr
Definition: ManagedStatic.h:53
bool isConstructed() const
isConstructed - Return true if this object has not been created yet.
Definition: ManagedStatic.h:73
LLVM_ABI void destroy() const
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:85
const C * operator->() const
const C & operator*() const
Definition: ManagedStatic.h:98
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
LLVM_ABI void llvm_shutdown()
llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
#define N
llvm_shutdown_obj - This is a simple helper class that calls llvm_shutdown() when it is destroyed.
object_creator - Helper method for ManagedStatic.
Definition: ManagedStatic.h:23
static void * call()
Definition: ManagedStatic.h:24
static void call(void *Ptr)
Definition: ManagedStatic.h:33
object_deleter - Helper method for ManagedStatic.
Definition: ManagedStatic.h:29
static void call(void *Ptr)
Definition: ManagedStatic.h:30