blob: 441f24e05afc589e597aa288737e060edcdd0699 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===-- llvm/Support/ManagedStatic.h - Static Global wrapper ----*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
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
16#include <atomic>
17#include <cstddef>
18
19namespace llvm {
20
21/// object_creator - Helper method for ManagedStatic.
22template <class C> struct object_creator {
23 static void *call() { return new C(); }
24};
25
26/// object_deleter - Helper method for ManagedStatic.
27///
28template <typename T> struct object_deleter {
29 static void call(void *Ptr) { delete (T *)Ptr; }
30};
31template <typename T, size_t N> struct object_deleter<T[N]> {
32 static void call(void *Ptr) { delete[](T *)Ptr; }
33};
34
35/// ManagedStaticBase - Common base class for ManagedStatic instances.
36class ManagedStaticBase {
37protected:
38 // This should only be used as a static variable, which guarantees that this
39 // will be zero initialized.
40 mutable std::atomic<void *> Ptr;
41 mutable void (*DeleterFn)(void*);
42 mutable const ManagedStaticBase *Next;
43
44 void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const;
45
46public:
47 /// isConstructed - Return true if this object has not been created yet.
48 bool isConstructed() const { return Ptr != nullptr; }
49
50 void destroy() const;
51};
52
53/// ManagedStatic - This transparently changes the behavior of global statics to
54/// be lazily constructed on demand (good for reducing startup times of dynamic
55/// libraries that link in LLVM components) and for making destruction be
56/// explicit through the llvm_shutdown() function call.
57///
58template <class C, class Creator = object_creator<C>,
59 class Deleter = object_deleter<C>>
60class ManagedStatic : public ManagedStaticBase {
61public:
62 // Accessors.
63 C &operator*() {
64 void *Tmp = Ptr.load(std::memory_order_acquire);
65 if (!Tmp)
66 RegisterManagedStatic(Creator::call, Deleter::call);
67
68 return *static_cast<C *>(Ptr.load(std::memory_order_relaxed));
69 }
70
71 C *operator->() { return &**this; }
72
73 const C &operator*() const {
74 void *Tmp = Ptr.load(std::memory_order_acquire);
75 if (!Tmp)
76 RegisterManagedStatic(Creator::call, Deleter::call);
77
78 return *static_cast<C *>(Ptr.load(std::memory_order_relaxed));
79 }
80
81 const C *operator->() const { return &**this; }
82};
83
84/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
85void llvm_shutdown();
86
87/// llvm_shutdown_obj - This is a simple helper class that calls
88/// llvm_shutdown() when it is destroyed.
89struct llvm_shutdown_obj {
90 llvm_shutdown_obj() = default;
91 ~llvm_shutdown_obj() { llvm_shutdown(); }
92};
93
94} // end namespace llvm
95
96#endif // LLVM_SUPPORT_MANAGEDSTATIC_H