1771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner//===-- llvm/Support/ManagedStatic.h - Static Global wrapper ----*- C++ -*-===//
2771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner//
3771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner//                     The LLVM Compiler Infrastructure
4771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner//
57ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// This file is distributed under the University of Illinois Open Source
67ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// License. See LICENSE.TXT for details.
7771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner//
8771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner//===----------------------------------------------------------------------===//
9771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner//
10771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner// This file defines the ManagedStatic class and the llvm_shutdown() function.
11771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner//
12771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner//===----------------------------------------------------------------------===//
13771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner
14771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner#ifndef LLVM_SUPPORT_MANAGED_STATIC_H
15771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner#define LLVM_SUPPORT_MANAGED_STATIC_H
16771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner
171f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Atomic.h"
181f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Threading.h"
194d0a9ff36574da0c042e9bd3ae816301b392ac41Nick Lewycky#include "llvm/Support/Valgrind.h"
20b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson
21771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnernamespace llvm {
22771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner
23b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson/// object_creator - Helper method for ManagedStatic.
24b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Andersontemplate<class C>
25b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Andersonvoid* object_creator() {
26b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson  return new C();
27b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson}
28b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson
29771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner/// object_deleter - Helper method for ManagedStatic.
30771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner///
3180c8c3178276d0988c0129fb235f5b08a2e4f66dAlisdair Meredithtemplate<typename T> struct object_deleter {
3280c8c3178276d0988c0129fb235f5b08a2e4f66dAlisdair Meredith  static void call(void * Ptr) { delete (T*)Ptr; }
3380c8c3178276d0988c0129fb235f5b08a2e4f66dAlisdair Meredith};
3480c8c3178276d0988c0129fb235f5b08a2e4f66dAlisdair Meredithtemplate<typename T, size_t N> struct object_deleter<T[N]> {
3580c8c3178276d0988c0129fb235f5b08a2e4f66dAlisdair Meredith  static void call(void * Ptr) { delete[] (T*)Ptr; }
3680c8c3178276d0988c0129fb235f5b08a2e4f66dAlisdair Meredith};
37771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner
38771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner/// ManagedStaticBase - Common base class for ManagedStatic instances.
39771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnerclass ManagedStaticBase {
40771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnerprotected:
41771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  // This should only be used as a static variable, which guarantees that this
42771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  // will be zero initialized.
43771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  mutable void *Ptr;
44771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  mutable void (*DeleterFn)(void*);
45771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  mutable const ManagedStaticBase *Next;
46fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman
47b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson  void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const;
48771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnerpublic:
49fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman  /// isConstructed - Return true if this object has not been created yet.
50dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  bool isConstructed() const { return Ptr != nullptr; }
51fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman
52771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  void destroy() const;
53771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner};
54771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner
55771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner/// ManagedStatic - This transparently changes the behavior of global statics to
56771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner/// be lazily constructed on demand (good for reducing startup times of dynamic
57771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner/// libraries that link in LLVM components) and for making destruction be
58771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner/// explicit through the llvm_shutdown() function call.
59771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner///
60771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnertemplate<class C>
61771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnerclass ManagedStatic : public ManagedStaticBase {
62ca37b511fa1e542c936402c0023455fd9a444e76Owen Andersonpublic:
63ca37b511fa1e542c936402c0023455fd9a444e76Owen Anderson
64ca37b511fa1e542c936402c0023455fd9a444e76Owen Anderson  // Accessors.
65ca37b511fa1e542c936402c0023455fd9a444e76Owen Anderson  C &operator*() {
66b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson    void* tmp = Ptr;
6794fefe27f574ed98ad2522f8a7d1515e698ff036Owen Anderson    if (llvm_is_multithreaded()) sys::MemoryFence();
6880c8c3178276d0988c0129fb235f5b08a2e4f66dAlisdair Meredith    if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
694d0a9ff36574da0c042e9bd3ae816301b392ac41Nick Lewycky    TsanHappensAfter(this);
70b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson
71771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner    return *static_cast<C*>(Ptr);
72771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  }
73771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  C *operator->() {
74b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson    void* tmp = Ptr;
7594fefe27f574ed98ad2522f8a7d1515e698ff036Owen Anderson    if (llvm_is_multithreaded()) sys::MemoryFence();
7680c8c3178276d0988c0129fb235f5b08a2e4f66dAlisdair Meredith    if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
774d0a9ff36574da0c042e9bd3ae816301b392ac41Nick Lewycky    TsanHappensAfter(this);
78b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson
79771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner    return static_cast<C*>(Ptr);
80771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  }
81771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  const C &operator*() const {
82b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson    void* tmp = Ptr;
8394fefe27f574ed98ad2522f8a7d1515e698ff036Owen Anderson    if (llvm_is_multithreaded()) sys::MemoryFence();
8480c8c3178276d0988c0129fb235f5b08a2e4f66dAlisdair Meredith    if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
854d0a9ff36574da0c042e9bd3ae816301b392ac41Nick Lewycky    TsanHappensAfter(this);
86b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson
87771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner    return *static_cast<C*>(Ptr);
88771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  }
89771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  const C *operator->() const {
90b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson    void* tmp = Ptr;
9194fefe27f574ed98ad2522f8a7d1515e698ff036Owen Anderson    if (llvm_is_multithreaded()) sys::MemoryFence();
9280c8c3178276d0988c0129fb235f5b08a2e4f66dAlisdair Meredith    if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call);
934d0a9ff36574da0c042e9bd3ae816301b392ac41Nick Lewycky    TsanHappensAfter(this);
94fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman
95b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson    return static_cast<C*>(Ptr);
96771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  }
97771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner};
98771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner
99771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
100771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnervoid llvm_shutdown();
101771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner
102bdbf5fd1c9cfa30a348596b127394fa1f4caf033Chris Lattner/// llvm_shutdown_obj - This is a simple helper class that calls
103bdbf5fd1c9cfa30a348596b127394fa1f4caf033Chris Lattner/// llvm_shutdown() when it is destroyed.
104bdbf5fd1c9cfa30a348596b127394fa1f4caf033Chris Lattnerstruct llvm_shutdown_obj {
105b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson  llvm_shutdown_obj() { }
106bdbf5fd1c9cfa30a348596b127394fa1f4caf033Chris Lattner  ~llvm_shutdown_obj() { llvm_shutdown(); }
107bdbf5fd1c9cfa30a348596b127394fa1f4caf033Chris Lattner};
108fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman
109771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner}
110771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner
111771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner#endif
112