]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/tools/clang/include/clang/Basic/DelayedCleanupPool.h
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / llvm / tools / clang / include / clang / Basic / DelayedCleanupPool.h
1 //=== DelayedCleanupPool.h - Delayed Clean-up Pool Implementation *- 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 a facility to delay calling cleanup methods until specific
11 // points.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_CLANG_BASIC_DELAYEDCLEANUPPOOL_H
16 #define LLVM_CLANG_BASIC_DELAYEDCLEANUPPOOL_H
17
18 #include "clang/Basic/LLVM.h"
19 #include "llvm/ADT/DenseMap.h"
20 #include "llvm/ADT/SmallVector.h"
21
22 namespace clang {
23
24 /// \brief Gathers pairs of pointer-to-object/pointer-to-cleanup-function
25 /// allowing the cleanup functions to get called (with the pointer as parameter)
26 /// at specific points.
27 ///
28 /// The use case is to simplify clean-up of certain resources that, while their
29 /// lifetime is well-known and restricted, cleaning them up manually is easy to
30 /// miss and cause a leak.
31 ///
32 /// The same pointer can be added multiple times; its clean-up function will
33 /// only be called once.
34 class DelayedCleanupPool {
35 public:
36   typedef void (*CleanupFn)(void *ptr);
37
38   /// \brief Adds a pointer and its associated cleanup function to be called
39   /// at a later point.
40   ///
41   /// \returns false if the pointer is already added, true otherwise.
42   bool delayCleanup(void *ptr, CleanupFn fn) {
43     assert(ptr && "Expected valid pointer to object");
44     assert(fn && "Expected valid pointer to function");
45
46     CleanupFn &mapFn = Ptrs[ptr];
47     assert((!mapFn || mapFn == fn) &&
48            "Adding a pointer with different cleanup function!");
49
50     if (!mapFn) {
51       mapFn = fn;
52       Cleanups.push_back(std::make_pair(ptr, fn));
53       return true;
54     }
55
56     return false;
57   }
58
59   template <typename T>
60   bool delayDelete(T *ptr) {
61     return delayCleanup(ptr, cleanupWithDelete<T>);
62   }
63
64   template <typename T, void (T::*Fn)()>
65   bool delayMemberFunc(T *ptr) {
66     return delayCleanup(ptr, cleanupWithMemberFunc<T, Fn>);
67   }
68
69   void doCleanup() {
70     for (SmallVector<std::pair<void *, CleanupFn>, 8>::reverse_iterator
71            I = Cleanups.rbegin(), E = Cleanups.rend(); I != E; ++I)
72       I->second(I->first);
73     Cleanups.clear();
74     Ptrs.clear();
75   }
76
77   ~DelayedCleanupPool() {
78     doCleanup();
79   }
80
81 private:
82   llvm::DenseMap<void *, CleanupFn> Ptrs;
83   SmallVector<std::pair<void *, CleanupFn>, 8> Cleanups;
84
85   template <typename T>
86   static void cleanupWithDelete(void *ptr) {
87     delete static_cast<T *>(ptr);
88   }
89
90   template <typename T, void (T::*Fn)()>
91   static void cleanupWithMemberFunc(void *ptr) {
92     (static_cast<T *>(ptr)->*Fn)();
93   }
94 };
95
96 /// \brief RAII object for triggering a cleanup of a DelayedCleanupPool.
97 class DelayedCleanupPoint {
98   DelayedCleanupPool &Pool;
99
100 public:
101   DelayedCleanupPoint(DelayedCleanupPool &pool) : Pool(pool) { }
102
103   ~DelayedCleanupPoint() {
104     Pool.doCleanup();
105   }
106 };
107
108 } // end namespace clang
109
110 #endif