diff options
author | dim <dim@FreeBSD.org> | 2011-07-17 15:40:56 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-07-17 15:40:56 +0000 |
commit | 611ba3ea3300b71eb95dc4e45f20eee5dddd32e1 (patch) | |
tree | 2097d084eb235c0b12c0bff3445f4ec7bbaa8a12 /include/clang/Basic/DelayedCleanupPool.h | |
parent | c49018d9cce52d8c9f34b44865ec3ba8e89a1488 (diff) | |
download | FreeBSD-src-611ba3ea3300b71eb95dc4e45f20eee5dddd32e1.zip FreeBSD-src-611ba3ea3300b71eb95dc4e45f20eee5dddd32e1.tar.gz |
Vendor import of clang trunk r135360:
http://llvm.org/svn/llvm-project/cfe/trunk@135360
Diffstat (limited to 'include/clang/Basic/DelayedCleanupPool.h')
-rw-r--r-- | include/clang/Basic/DelayedCleanupPool.h | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/include/clang/Basic/DelayedCleanupPool.h b/include/clang/Basic/DelayedCleanupPool.h new file mode 100644 index 0000000..843205f --- /dev/null +++ b/include/clang/Basic/DelayedCleanupPool.h @@ -0,0 +1,109 @@ +//=== DelayedCleanupPool.h - Delayed Clean-up Pool Implementation *- C++ -*===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a facility to delay calling cleanup methods until specific +// points. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_DELAYEDCLEANUPPOOL_H +#define LLVM_CLANG_BASIC_DELAYEDCLEANUPPOOL_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { + +/// \brief Gathers pairs of pointer-to-object/pointer-to-cleanup-function +/// allowing the cleanup functions to get called (with the pointer as parameter) +/// at specific points. +/// +/// The use case is to simplify clean-up of certain resources that, while their +/// lifetime is well-known and restricted, cleaning them up manually is easy to +/// miss and cause a leak. +/// +/// The same pointer can be added multiple times; its clean-up function will +/// only be called once. +class DelayedCleanupPool { +public: + typedef void (*CleanupFn)(void *ptr); + + /// \brief Adds a pointer and its associated cleanup function to be called + /// at a later point. + /// + /// \returns false if the pointer is already added, true otherwise. + bool delayCleanup(void *ptr, CleanupFn fn) { + assert(ptr && "Expected valid pointer to object"); + assert(fn && "Expected valid pointer to function"); + + CleanupFn &mapFn = Ptrs[ptr]; + assert((!mapFn || mapFn == fn) && + "Adding a pointer with different cleanup function!"); + + if (!mapFn) { + mapFn = fn; + Cleanups.push_back(std::make_pair(ptr, fn)); + return true; + } + + return false; + } + + template <typename T> + bool delayDelete(T *ptr) { + return delayCleanup(ptr, cleanupWithDelete<T>); + } + + template <typename T, void (T::*Fn)()> + bool delayMemberFunc(T *ptr) { + return delayCleanup(ptr, cleanupWithMemberFunc<T, Fn>); + } + + void doCleanup() { + for (llvm::SmallVector<std::pair<void *, CleanupFn>, 8>::reverse_iterator + I = Cleanups.rbegin(), E = Cleanups.rend(); I != E; ++I) + I->second(I->first); + Cleanups.clear(); + Ptrs.clear(); + } + + ~DelayedCleanupPool() { + doCleanup(); + } + +private: + llvm::DenseMap<void *, CleanupFn> Ptrs; + llvm::SmallVector<std::pair<void *, CleanupFn>, 8> Cleanups; + + template <typename T> + static void cleanupWithDelete(void *ptr) { + delete static_cast<T *>(ptr); + } + + template <typename T, void (T::*Fn)()> + static void cleanupWithMemberFunc(void *ptr) { + (static_cast<T *>(ptr)->*Fn)(); + } +}; + +/// \brief RAII object for triggering a cleanup of a DelayedCleanupPool. +class DelayedCleanupPoint { + DelayedCleanupPool &Pool; + +public: + DelayedCleanupPoint(DelayedCleanupPool &pool) : Pool(pool) { } + + ~DelayedCleanupPoint() { + Pool.doCleanup(); + } +}; + +} // end namespace clang + +#endif |