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