ManagedStatic.h revision 94fefe27f574ed98ad2522f8a7d1515e698ff036
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
17b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson#include "llvm/System/Atomic.h"
18e3cd5ca7e79f4359e8a101c211fc9c117eb62347Owen Anderson#include "llvm/System/Threading.h"
19b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson
20771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnernamespace llvm {
21771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner
22b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson/// object_creator - Helper method for ManagedStatic.
23b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Andersontemplate<class C>
24b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Andersonvoid* object_creator() {
25b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson  return new C();
26b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson}
27b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson
28771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner/// object_deleter - Helper method for ManagedStatic.
29771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner///
30771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnertemplate<class C>
31771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnervoid object_deleter(void *Ptr) {
32771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  delete (C*)Ptr;
33771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner}
34771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner
35771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner/// ManagedStaticBase - Common base class for ManagedStatic instances.
36771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnerclass ManagedStaticBase {
37771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnerprotected:
38771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  // This should only be used as a static variable, which guarantees that this
39771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  // will be zero initialized.
40771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  mutable void *Ptr;
41771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  mutable void (*DeleterFn)(void*);
42771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  mutable const ManagedStaticBase *Next;
43fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman
44b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson  void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const;
45771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnerpublic:
46fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman  /// isConstructed - Return true if this object has not been created yet.
4768ce9ba666a7eb8c7eb3fb7888e4418fffd2e716Chris Lattner  bool isConstructed() const { return Ptr != 0; }
48fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman
49771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  void destroy() const;
50771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner};
51771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner
52771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner/// ManagedStatic - This transparently changes the behavior of global statics to
53771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner/// be lazily constructed on demand (good for reducing startup times of dynamic
54771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner/// libraries that link in LLVM components) and for making destruction be
55771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner/// explicit through the llvm_shutdown() function call.
56771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner///
57771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnertemplate<class C>
58771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnerclass ManagedStatic : public ManagedStaticBase {
59ca37b511fa1e542c936402c0023455fd9a444e76Owen Andersonpublic:
60ca37b511fa1e542c936402c0023455fd9a444e76Owen Anderson
61ca37b511fa1e542c936402c0023455fd9a444e76Owen Anderson  // Accessors.
62ca37b511fa1e542c936402c0023455fd9a444e76Owen Anderson  C &operator*() {
63b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson    void* tmp = Ptr;
6494fefe27f574ed98ad2522f8a7d1515e698ff036Owen Anderson    if (llvm_is_multithreaded()) sys::MemoryFence();
65b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson    if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>);
66b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson
67771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner    return *static_cast<C*>(Ptr);
68771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  }
69771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  C *operator->() {
70b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson    void* tmp = Ptr;
7194fefe27f574ed98ad2522f8a7d1515e698ff036Owen Anderson    if (llvm_is_multithreaded()) sys::MemoryFence();
72b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson    if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>);
73b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson
74771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner    return static_cast<C*>(Ptr);
75771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  }
76771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  const C &operator*() const {
77b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson    void* tmp = Ptr;
7894fefe27f574ed98ad2522f8a7d1515e698ff036Owen Anderson    if (llvm_is_multithreaded()) sys::MemoryFence();
79b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson    if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>);
80b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson
81771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner    return *static_cast<C*>(Ptr);
82771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  }
83771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  const C *operator->() const {
84b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson    void* tmp = Ptr;
8594fefe27f574ed98ad2522f8a7d1515e698ff036Owen Anderson    if (llvm_is_multithreaded()) sys::MemoryFence();
86b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson    if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>);
87fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman
88b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson    return static_cast<C*>(Ptr);
89771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner  }
90771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner};
91771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner
92b4d7e35dde3ccbe0dc10bf13332ade9812586dd0Chris Lattnertemplate<void (*CleanupFn)(void*)>
93b4d7e35dde3ccbe0dc10bf13332ade9812586dd0Chris Lattnerclass ManagedCleanup : public ManagedStaticBase {
94b4d7e35dde3ccbe0dc10bf13332ade9812586dd0Chris Lattnerpublic:
95b4d7e35dde3ccbe0dc10bf13332ade9812586dd0Chris Lattner  void Register() { RegisterManagedStatic(0, CleanupFn); }
96b4d7e35dde3ccbe0dc10bf13332ade9812586dd0Chris Lattner};
97b4d7e35dde3ccbe0dc10bf13332ade9812586dd0Chris Lattner
98771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
99771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnervoid llvm_shutdown();
100771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner
101fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman
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() { }
106b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson  explicit llvm_shutdown_obj(bool multithreaded) {
107b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson    if (multithreaded) llvm_start_multithreaded();
108b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson  }
109bdbf5fd1c9cfa30a348596b127394fa1f4caf033Chris Lattner  ~llvm_shutdown_obj() { llvm_shutdown(); }
110bdbf5fd1c9cfa30a348596b127394fa1f4caf033Chris Lattner};
111fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman
112771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner}
113771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner
114771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner#endif
115