1285SN/A//===-- llvm/Support/ManagedStatic.h - Static Global wrapper ----*- C++ -*-===//
2461SN/A//
3285SN/A//                     The LLVM Compiler Infrastructure
4285SN/A//
5285SN/A// This file is distributed under the University of Illinois Open Source
6285SN/A// License. See LICENSE.TXT for details.
7285SN/A//
8285SN/A//===----------------------------------------------------------------------===//
9285SN/A//
10285SN/A// This file defines the ManagedStatic class and the llvm_shutdown() function.
11285SN/A//
12285SN/A//===----------------------------------------------------------------------===//
13285SN/A
14285SN/A#ifndef LLVM_SUPPORT_MANAGED_STATIC_H
15285SN/A#define LLVM_SUPPORT_MANAGED_STATIC_H
16285SN/A
17285SN/A#include "llvm/Support/Atomic.h"
18285SN/A#include "llvm/Support/Threading.h"
19285SN/A#include "llvm/Support/Valgrind.h"
20285SN/A
21285SN/Anamespace llvm {
22285SN/A
23285SN/A/// object_creator - Helper method for ManagedStatic.
24285SN/Atemplate<class C>
25285SN/Avoid* object_creator() {
26285SN/A  return new C();
27285SN/A}
28285SN/A
29285SN/A/// object_deleter - Helper method for ManagedStatic.
30285SN/A///
31285SN/Atemplate<typename T> struct object_deleter {
32285SN/A  static void call(void * Ptr) { delete (T*)Ptr; }
33285SN/A};
34285SN/Atemplate<typename T, size_t N> struct object_deleter<T[N]> {
35285SN/A  static void call(void * Ptr) { delete[] (T*)Ptr; }
36285SN/A};
37285SN/A
38285SN/A/// ManagedStaticBase - Common base class for ManagedStatic instances.
39285SN/Aclass ManagedStaticBase {
40285SN/Aprotected:
41285SN/A  // This should only be used as a static variable, which guarantees that this
42285SN/A  // will be zero initialized.
43285SN/A  mutable void *Ptr;
44285SN/A  mutable void (*DeleterFn)(void*);
45285SN/A  mutable const ManagedStaticBase *Next;
46285SN/A
47285SN/A  void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const;
48285SN/Apublic:
49285SN/A  /// isConstructed - Return true if this object has not been created yet.
50285SN/A  bool isConstructed() const { return Ptr != 0; }
51285SN/A
52285SN/A  void destroy() const;
53285SN/A};
54285SN/A
55285SN/A/// ManagedStatic - This transparently changes the behavior of global statics to
56285SN/A/// be lazily constructed on demand (good for reducing startup times of dynamic
57285SN/A/// libraries that link in LLVM components) and for making destruction be
58285SN/A/// explicit through the llvm_shutdown() function call.
59285SN/A///
60285SN/Atemplate<class C>
61285SN/Aclass ManagedStatic : public ManagedStaticBase {
62285SN/Apublic:
63285SN/A
64285SN/A  // Accessors.
65285SN/A  C &operator*() {
66285SN/A    void* tmp = Ptr;
67285SN/A    if (llvm_is_multithreaded()) sys::MemoryFence();
68285SN/A    if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
69285SN/A    TsanHappensAfter(this);
70285SN/A
71285SN/A    return *static_cast<C*>(Ptr);
72285SN/A  }
73  C *operator->() {
74    void* tmp = Ptr;
75    if (llvm_is_multithreaded()) sys::MemoryFence();
76    if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
77    TsanHappensAfter(this);
78
79    return static_cast<C*>(Ptr);
80  }
81  const C &operator*() const {
82    void* tmp = Ptr;
83    if (llvm_is_multithreaded()) sys::MemoryFence();
84    if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
85    TsanHappensAfter(this);
86
87    return *static_cast<C*>(Ptr);
88  }
89  const C *operator->() const {
90    void* tmp = Ptr;
91    if (llvm_is_multithreaded()) sys::MemoryFence();
92    if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
93    TsanHappensAfter(this);
94
95    return static_cast<C*>(Ptr);
96  }
97};
98
99/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
100void llvm_shutdown();
101
102/// llvm_shutdown_obj - This is a simple helper class that calls
103/// llvm_shutdown() when it is destroyed.
104struct llvm_shutdown_obj {
105  llvm_shutdown_obj() { }
106  explicit llvm_shutdown_obj(bool multithreaded) {
107    if (multithreaded) llvm_start_multithreaded();
108  }
109  ~llvm_shutdown_obj() { llvm_shutdown(); }
110};
111
112}
113
114#endif
115