diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h index 28b31f3a782..759d2f8c718 100644 --- a/include/llvm/Support/CrashRecoveryContext.h +++ b/include/llvm/Support/CrashRecoveryContext.h @@ -98,89 +98,97 @@ public: }; class CrashRecoveryContextCleanup { +protected: + CrashRecoveryContext *context; + CrashRecoveryContextCleanup(CrashRecoveryContext *context) + : context(context) {} public: bool cleanupFired; - enum ProvidedCleanups { DeleteCleanup, DestructorCleanup }; CrashRecoveryContextCleanup() : cleanupFired(false) {} virtual ~CrashRecoveryContextCleanup(); virtual void recoverResources() = 0; - - template static CrashRecoveryContextCleanup *create(T *, - ProvidedCleanups cleanupKind = - CrashRecoveryContextCleanup::DeleteCleanup); - + + CrashRecoveryContext *getContext() const { + return context; + } + private: friend class CrashRecoveryContext; CrashRecoveryContextCleanup *prev, *next; }; -template -class CrashRecoveryContextDestructorCleanup - : public CrashRecoveryContextCleanup -{ +template +class CrashRecoveryContextCleanupBase : public CrashRecoveryContextCleanup { +protected: T *resource; + CrashRecoveryContextCleanupBase(CrashRecoveryContext *context, T* resource) + : CrashRecoveryContextCleanup(context), resource(resource) {} public: - CrashRecoveryContextDestructorCleanup(T *resource) : resource(resource) {} - virtual void recoverResources() { - resource->~T(); - } -}; - -template -class CrashRecoveryContextDeleteCleanup - : public CrashRecoveryContextCleanup -{ - T *resource; -public: - CrashRecoveryContextDeleteCleanup(T *resource) : resource(resource) {} - virtual void recoverResources() { - delete resource; - } -}; - -template -struct CrashRecoveryContextTrait { - static inline CrashRecoveryContextCleanup * - createCleanup(T *resource, - CrashRecoveryContextCleanup::ProvidedCleanups cleanup) { - switch (cleanup) { - case CrashRecoveryContextCleanup::DeleteCleanup: - return new CrashRecoveryContextDeleteCleanup(resource); - case CrashRecoveryContextCleanup::DestructorCleanup: - return new CrashRecoveryContextDestructorCleanup(resource); + static DERIVED *create(T *x) { + if (x) { + if (CrashRecoveryContext *context = CrashRecoveryContext::GetCurrent()) + return new DERIVED(context, x); } return 0; } }; -template -inline CrashRecoveryContextCleanup* -CrashRecoveryContextCleanup::create(T *x, - CrashRecoveryContextCleanup::ProvidedCleanups cleanupKind) { - return CrashRecoveryContext::GetCurrent() ? - CrashRecoveryContextTrait::createCleanup(x, cleanupKind) : - 0; -} +template +class CrashRecoveryContextDestructorCleanup : public + CrashRecoveryContextCleanupBase, T> { +public: + CrashRecoveryContextDestructorCleanup(CrashRecoveryContext *context, + T *resource) + : CrashRecoveryContextCleanupBase< + CrashRecoveryContextDestructorCleanup, T>(context, resource) {} + virtual void recoverResources() { + this->resource->~T(); + } +}; + +template +class CrashRecoveryContextDeleteCleanup : public + CrashRecoveryContextCleanupBase, T> { +public: + CrashRecoveryContextDeleteCleanup(CrashRecoveryContext *context, T *resource) + : CrashRecoveryContextCleanupBase< + CrashRecoveryContextDeleteCleanup, T>(context, resource) {} + + virtual void recoverResources() { + delete this->resource; + } +}; + +template +class CrashRecoveryContextReleaseRefCleanup : public + CrashRecoveryContextCleanupBase, T> +{ +public: + CrashRecoveryContextReleaseRefCleanup(CrashRecoveryContext *context, + T *resource) + : CrashRecoveryContextCleanupBase, + T>(context, resource) {} + + virtual void recoverResources() { + this->resource->Release(); + } +}; + +template > class CrashRecoveryContextCleanupRegistrar { - CrashRecoveryContext *context; CrashRecoveryContextCleanup *cleanup; public: - CrashRecoveryContextCleanupRegistrar(CrashRecoveryContextCleanup *cleanup) - : context(CrashRecoveryContext::GetCurrent()), - cleanup(cleanup) - { - if (context && cleanup) - context->registerCleanup(cleanup); + CrashRecoveryContextCleanupRegistrar(T *x) + : cleanup(Cleanup::create(x)) { + if (cleanup) + cleanup->getContext()->registerCleanup(cleanup); } + ~CrashRecoveryContextCleanupRegistrar() { - if (cleanup && !cleanup->cleanupFired) { - if (context) - context->unregisterCleanup(cleanup); - else - delete cleanup; - } + if (cleanup && !cleanup->cleanupFired) + cleanup->getContext()->unregisterCleanup(cleanup); } }; }