Factor out some common code, fix more typoes, and add a memory fence that might be...
[oota-llvm.git] / include / llvm / Support / ManagedStatic.h
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_MANAGED_STATIC_H
15 #define LLVM_SUPPORT_MANAGED_STATIC_H
16
17 #include "llvm/System/Atomic.h"
18
19 namespace llvm {
20
21 /// object_deleter - Helper method for ManagedStatic.
22 ///
23 template<class C>
24 void object_deleter(void *Ptr) {
25   delete (C*)Ptr;
26 }
27
28 /// ManagedStaticBase - Common base class for ManagedStatic instances.
29 class ManagedStaticBase {
30 protected:
31   mutable sys::cas_flag InitFlag;
32   
33   // This should only be used as a static variable, which guarantees that this
34   // will be zero initialized.
35   mutable void *Ptr;
36   mutable void (*DeleterFn)(void*);
37   mutable const ManagedStaticBase *Next;
38
39   void RegisterManagedStatic(void *ObjPtr, void (*deleter)(void*)) const;
40 public:
41   /// isConstructed - Return true if this object has not been created yet.
42   bool isConstructed() const { return Ptr != 0; }
43
44   void destroy() const;
45 };
46
47 /// ManagedStatic - This transparently changes the behavior of global statics to
48 /// be lazily constructed on demand (good for reducing startup times of dynamic
49 /// libraries that link in LLVM components) and for making destruction be
50 /// explicit through the llvm_shutdown() function call.
51 ///
52 template<class C>
53 class ManagedStatic : public ManagedStaticBase {
54 private:
55   void checkInit() {
56     sys::cas_flag OldFlag = sys::CompareAndSwap(&InitFlag, 1, 0);
57     if (OldFlag == 0) {
58       LazyInit();
59       sys::MemoryFence();
60       InitFlag = 2;
61     } else if (OldFlag == 1) {
62       while (InitFlag == 1) ;
63       sys::MemoryFence();
64     }
65   }
66 public:
67
68   // Accessors.
69   C &operator*() {
70     checkInit();
71     return *static_cast<C*>(Ptr);
72   }
73   C *operator->() {
74     checkInit();
75     return static_cast<C*>(Ptr);
76   }
77   const C &operator*() const {
78     checkInit();
79     return *static_cast<C*>(Ptr);
80   }
81   const C *operator->() const {
82     checkInit();
83     return static_cast<C*>(Ptr);
84   }
85
86 public:
87   void LazyInit() const {
88     RegisterManagedStatic(new C(), object_deleter<C>);
89   }
90 };
91
92 template<void (*CleanupFn)(void*)>
93 class ManagedCleanup : public ManagedStaticBase {
94 public:
95   void Register() { RegisterManagedStatic(0, CleanupFn); }
96 };
97
98
99 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
100 void llvm_shutdown();
101
102
103 /// llvm_shutdown_obj - This is a simple helper class that calls
104 /// llvm_shutdown() when it is destroyed.
105 struct llvm_shutdown_obj {
106   llvm_shutdown_obj() {}
107   ~llvm_shutdown_obj() { llvm_shutdown(); }
108 };
109
110 }
111
112 #endif