X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FSupport%2FCrashRecoveryContext.h;h=4c0a5e26f00f0e80fe7d043238eead8f79457cb8;hb=2fa8af224ea026f9432e833fd6f42a216423a010;hp=2e9b5d4aa541eaed4d86ca5dd556fc873c5ad478;hpb=f8254d647352f8f194b4753a25d582758289e497;p=oota-llvm.git diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h index 2e9b5d4aa54..4c0a5e26f00 100644 --- a/include/llvm/Support/CrashRecoveryContext.h +++ b/include/llvm/Support/CrashRecoveryContext.h @@ -15,6 +15,8 @@ namespace llvm { class StringRef; +class CrashRecoveryContextCleanup; + /// \brief Crash recovery helper object. /// /// This class implements support for running operations in a safe context so @@ -42,10 +44,14 @@ class StringRef; /// Crash recovery contexts may not be nested. class CrashRecoveryContext { void *Impl; + CrashRecoveryContextCleanup *head; public: - CrashRecoveryContext() : Impl(0) {} + CrashRecoveryContext() : Impl(0), head(0) {} ~CrashRecoveryContext(); + + void registerCleanup(CrashRecoveryContextCleanup *cleanup); + void unregisterCleanup(CrashRecoveryContextCleanup *cleanup); /// \brief Enable crash recovery. static void Enable(); @@ -57,6 +63,10 @@ public: /// thread which is in a protected context. static CrashRecoveryContext *GetCurrent(); + /// \brief Return true if the current thread is recovering from a + /// crash. + static bool isRecoveringFromCrash(); + /// \brief Execute the provide callback function (with the given arguments) in /// a protected context. /// @@ -87,6 +97,104 @@ public: const std::string &getBacktrace() const; }; +class CrashRecoveryContextCleanup { +protected: + CrashRecoveryContext *context; + CrashRecoveryContextCleanup(CrashRecoveryContext *context) + : context(context), cleanupFired(false) {} +public: + bool cleanupFired; + + virtual ~CrashRecoveryContextCleanup(); + virtual void recoverResources() = 0; + + CrashRecoveryContext *getContext() const { + return context; + } + +private: + friend class CrashRecoveryContext; + CrashRecoveryContextCleanup *prev, *next; +}; + +template +class CrashRecoveryContextCleanupBase : public CrashRecoveryContextCleanup { +protected: + T *resource; + CrashRecoveryContextCleanupBase(CrashRecoveryContext *context, T* resource) + : CrashRecoveryContextCleanup(context), resource(resource) {} +public: + static DERIVED *create(T *x) { + if (x) { + if (CrashRecoveryContext *context = CrashRecoveryContext::GetCurrent()) + return new DERIVED(context, x); + } + return 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 { + CrashRecoveryContextCleanup *cleanup; +public: + CrashRecoveryContextCleanupRegistrar(T *x) + : cleanup(Cleanup::create(x)) { + if (cleanup) + cleanup->getContext()->registerCleanup(cleanup); + } + + ~CrashRecoveryContextCleanupRegistrar() { + unregister(); + } + + void unregister() { + if (cleanup && !cleanup->cleanupFired) + cleanup->getContext()->unregisterCleanup(cleanup); + cleanup = 0; + } +}; } #endif