Rework CrashRecoveryContextCleanup to provide a simpler way to create cleanup objects, and provide a new cleanup for

decrementing reference counts of objects with intrusive reference counts.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128055 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ted Kremenek
2011-03-22 01:15:10 +00:00
parent 116e2348ed
commit afc9e06021

View File

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