Now with working on Leopard!
[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 public:
55
56   // Accessors.
57   C &operator*() {
58     sys::cas_flag OldFlag = sys::CompareAndSwap(&InitFlag, 1, 0);
59     if (OldFlag == 0) {
60       LazyInit();
61       sys::MemoryFence();
62       InitFlag = 2;
63     } else if (OldFlag == 1)
64       while (OldFlag == 1) ;
65       
66     return *static_cast<C*>(Ptr);
67   }
68   C *operator->() {
69     sys::cas_flag OldFlag = sys::CompareAndSwap(&InitFlag, 1, 0);
70     if (OldFlag == 0) {
71       LazyInit();
72       sys::MemoryFence();
73       InitFlag = 2;
74     } else if (OldFlag == 1)
75       while (OldFlag == 1) ;
76     
77     return static_cast<C*>(Ptr);
78   }
79   const C &operator*() const {
80     sys::cas_flag OldFlag = sys::CompareAndSwap(&InitFlag, 1, 0);
81     if (OldFlag == 0) {
82       LazyInit();
83       sys::MemoryFence();
84       InitFlag = 2;
85     } else if (OldFlag == 1)
86       while (OldFlag == 1) ;
87     
88     return *static_cast<C*>(Ptr);
89   }
90   const C *operator->() const {
91     sys::cas_flag OldFlag = sys::CompareAndSwap(&InitFlag, 1, 0);
92     if (OldFlag == 0) {
93       LazyInit();
94       sys::MemoryFence();
95       InitFlag = 2;
96     } else if (OldFlag == 1)
97       while (OldFlag == 1) ;
98     
99     return static_cast<C*>(Ptr);
100   }
101
102 public:
103   void LazyInit() const {
104     RegisterManagedStatic(new C(), object_deleter<C>);
105   }
106 };
107
108 template<void (*CleanupFn)(void*)>
109 class ManagedCleanup : public ManagedStaticBase {
110 public:
111   void Register() { RegisterManagedStatic(0, CleanupFn); }
112 };
113
114
115 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
116 void llvm_shutdown();
117
118
119 /// llvm_shutdown_obj - This is a simple helper class that calls
120 /// llvm_shutdown() when it is destroyed.
121 struct llvm_shutdown_obj {
122   llvm_shutdown_obj() {}
123   ~llvm_shutdown_obj() { llvm_shutdown(); }
124 };
125
126 }
127
128 #endif