clang API Documentation

DelayedCleanupPool.h
Go to the documentation of this file.
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