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