1181053Srwatson//===-- llvm/Support/ManagedStatic.h - Static Global wrapper ----*- C++ -*-===//
2180701Srwatson//
3170407Srwatson//                     The LLVM Compiler Infrastructure
4155192Srwatson//
5155192Srwatson// This file is distributed under the University of Illinois Open Source
6155192Srwatson// License. See LICENSE.TXT for details.
7155192Srwatson//
8155192Srwatson//===----------------------------------------------------------------------===//
9155192Srwatson//
10155192Srwatson// This file defines the ManagedStatic class and the llvm_shutdown() function.
11155192Srwatson//
12155192Srwatson//===----------------------------------------------------------------------===//
13155192Srwatson
14180701Srwatson#ifndef LLVM_SUPPORT_MANAGED_STATIC_H
15155192Srwatson#define LLVM_SUPPORT_MANAGED_STATIC_H
16155192Srwatson
17155192Srwatson#include "llvm/Support/Atomic.h"
18155192Srwatson#include "llvm/Support/Threading.h"
19155192Srwatson#include "llvm/Support/Valgrind.h"
20155192Srwatson
21155192Srwatsonnamespace llvm {
22155192Srwatson
23155192Srwatson/// object_creator - Helper method for ManagedStatic.
24155192Srwatsontemplate<class C>
25155192Srwatsonvoid* object_creator() {
26155192Srwatson  return new C();
27155192Srwatson}
28155192Srwatson
29155192Srwatson/// object_deleter - Helper method for ManagedStatic.
30155192Srwatson///
31178186Srwatsontemplate<typename T> struct object_deleter {
32178186Srwatson  static void call(void * Ptr) { delete (T*)Ptr; }
33178186Srwatson};
34155192Srwatsontemplate<typename T, size_t N> struct object_deleter<T[N]> {
35155192Srwatson  static void call(void * Ptr) { delete[] (T*)Ptr; }
36155192Srwatson};
37155192Srwatson
38155192Srwatson/// ManagedStaticBase - Common base class for ManagedStatic instances.
39155192Srwatsonclass ManagedStaticBase {
40155192Srwatsonprotected:
41155192Srwatson  // This should only be used as a static variable, which guarantees that this
42155192Srwatson  // will be zero initialized.
43155192Srwatson  mutable void *Ptr;
44155192Srwatson  mutable void (*DeleterFn)(void*);
45155192Srwatson  mutable const ManagedStaticBase *Next;
46164033Srwatson
47155192Srwatson  void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const;
48155192Srwatsonpublic:
49155192Srwatson  /// isConstructed - Return true if this object has not been created yet.
50155192Srwatson  bool isConstructed() const { return Ptr != 0; }
51155192Srwatson
52155192Srwatson  void destroy() const;
53171144Srwatson};
54155192Srwatson
55155192Srwatson/// ManagedStatic - This transparently changes the behavior of global statics to
56155192Srwatson/// be lazily constructed on demand (good for reducing startup times of dynamic
57155192Srwatson/// libraries that link in LLVM components) and for making destruction be
58155192Srwatson/// explicit through the llvm_shutdown() function call.
59155192Srwatson///
60155192Srwatsontemplate<class C>
61155192Srwatsonclass ManagedStatic : public ManagedStaticBase {
62155192Srwatsonpublic:
63155406Srwatson
64156291Srwatson  // Accessors.
65155406Srwatson  C &operator*() {
66155406Srwatson    void* tmp = Ptr;
67155192Srwatson    if (llvm_is_multithreaded()) sys::MemoryFence();
68155192Srwatson    if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
69155192Srwatson    TsanHappensAfter(this);
70155192Srwatson
71155192Srwatson    return *static_cast<C*>(Ptr);
72155192Srwatson  }
73155406Srwatson  C *operator->() {
74155406Srwatson    void* tmp = Ptr;
75156888Srwatson    if (llvm_is_multithreaded()) sys::MemoryFence();
76170407Srwatson    if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
77155192Srwatson    TsanHappensAfter(this);
78155192Srwatson
79155192Srwatson    return static_cast<C*>(Ptr);
80155192Srwatson  }
81171144Srwatson  const C &operator*() const {
82171144Srwatson    void* tmp = Ptr;
83171144Srwatson    if (llvm_is_multithreaded()) sys::MemoryFence();
84155192Srwatson    if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
85170196Srwatson    TsanHappensAfter(this);
86170196Srwatson
87170196Srwatson    return *static_cast<C*>(Ptr);
88155192Srwatson  }
89155192Srwatson  const C *operator->() const {
90156889Srwatson    void* tmp = Ptr;
91156889Srwatson    if (llvm_is_multithreaded()) sys::MemoryFence();
92155192Srwatson    if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
93155192Srwatson    TsanHappensAfter(this);
94162176Srwatson
95162176Srwatson    return static_cast<C*>(Ptr);
96155192Srwatson  }
97156889Srwatson};
98156889Srwatson
99161813Swsalamon/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
100161813Swsalamonvoid llvm_shutdown();
101155192Srwatson
102155192Srwatson/// llvm_shutdown_obj - This is a simple helper class that calls
103155192Srwatson/// llvm_shutdown() when it is destroyed.
104155192Srwatsonstruct llvm_shutdown_obj {
105156889Srwatson  llvm_shutdown_obj() { }
106155192Srwatson  explicit llvm_shutdown_obj(bool multithreaded) {
107155192Srwatson    if (multithreaded) llvm_start_multithreaded();
108170691Srwatson  }
109155192Srwatson  ~llvm_shutdown_obj() { llvm_shutdown(); }
110156889Srwatson};
111155192Srwatson
112155192Srwatson}
113155192Srwatson
114155192Srwatson#endif
115156889Srwatson