clang API Documentation
00001 //=== DelayedCleanupPool.h - Delayed Clean-up Pool Implementation *- C++ -*===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines a facility to delay calling cleanup methods until specific 00011 // points. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_CLANG_BASIC_DELAYEDCLEANUPPOOL_H 00016 #define LLVM_CLANG_BASIC_DELAYEDCLEANUPPOOL_H 00017 00018 #include "clang/Basic/LLVM.h" 00019 #include "llvm/ADT/DenseMap.h" 00020 #include "llvm/ADT/SmallVector.h" 00021 00022 namespace clang { 00023 00024 /// \brief Gathers pairs of pointer-to-object/pointer-to-cleanup-function 00025 /// allowing the cleanup functions to get called (with the pointer as parameter) 00026 /// at specific points. 00027 /// 00028 /// The use case is to simplify clean-up of certain resources that, while their 00029 /// lifetime is well-known and restricted, cleaning them up manually is easy to 00030 /// miss and cause a leak. 00031 /// 00032 /// The same pointer can be added multiple times; its clean-up function will 00033 /// only be called once. 00034 class DelayedCleanupPool { 00035 public: 00036 typedef void (*CleanupFn)(void *ptr); 00037 00038 /// \brief Adds a pointer and its associated cleanup function to be called 00039 /// at a later point. 00040 /// 00041 /// \returns false if the pointer is already added, true otherwise. 00042 bool delayCleanup(void *ptr, CleanupFn fn) { 00043 assert(ptr && "Expected valid pointer to object"); 00044 assert(fn && "Expected valid pointer to function"); 00045 00046 CleanupFn &mapFn = Ptrs[ptr]; 00047 assert((!mapFn || mapFn == fn) && 00048 "Adding a pointer with different cleanup function!"); 00049 00050 if (!mapFn) { 00051 mapFn = fn; 00052 Cleanups.push_back(std::make_pair(ptr, fn)); 00053 return true; 00054 } 00055 00056 return false; 00057 } 00058 00059 template <typename T> 00060 bool delayDelete(T *ptr) { 00061 return delayCleanup(ptr, cleanupWithDelete<T>); 00062 } 00063 00064 template <typename T, void (T::*Fn)()> 00065 bool delayMemberFunc(T *ptr) { 00066 return delayCleanup(ptr, cleanupWithMemberFunc<T, Fn>); 00067 } 00068 00069 void doCleanup() { 00070 for (SmallVector<std::pair<void *, CleanupFn>, 8>::reverse_iterator 00071 I = Cleanups.rbegin(), E = Cleanups.rend(); I != E; ++I) 00072 I->second(I->first); 00073 Cleanups.clear(); 00074 Ptrs.clear(); 00075 } 00076 00077 ~DelayedCleanupPool() { 00078 doCleanup(); 00079 } 00080 00081 private: 00082 llvm::DenseMap<void *, CleanupFn> Ptrs; 00083 SmallVector<std::pair<void *, CleanupFn>, 8> Cleanups; 00084 00085 template <typename T> 00086 static void cleanupWithDelete(void *ptr) { 00087 delete static_cast<T *>(ptr); 00088 } 00089 00090 template <typename T, void (T::*Fn)()> 00091 static void cleanupWithMemberFunc(void *ptr) { 00092 (static_cast<T *>(ptr)->*Fn)(); 00093 } 00094 }; 00095 00096 /// \brief RAII object for triggering a cleanup of a DelayedCleanupPool. 00097 class DelayedCleanupPoint { 00098 DelayedCleanupPool &Pool; 00099 00100 public: 00101 DelayedCleanupPoint(DelayedCleanupPool &pool) : Pool(pool) { } 00102 00103 ~DelayedCleanupPoint() { 00104 Pool.doCleanup(); 00105 } 00106 }; 00107 00108 } // end namespace clang 00109 00110 #endif