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 {
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 <typename T> static CrashRecoveryContextCleanup *create(T *,
ProvidedCleanups cleanupKind =
CrashRecoveryContextCleanup::DeleteCleanup);
CrashRecoveryContext *getContext() const {
return context;
}
private:
friend class CrashRecoveryContext;
CrashRecoveryContextCleanup *prev, *next;
};
template <typename T>
class CrashRecoveryContextDestructorCleanup
: public CrashRecoveryContextCleanup
{
template<typename DERIVED, typename T>
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 <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);
static DERIVED *create(T *x) {
if (x) {
if (CrashRecoveryContext *context = CrashRecoveryContext::GetCurrent())
return new DERIVED(context, x);
}
return 0;
}
};
template<typename T>
inline CrashRecoveryContextCleanup*
CrashRecoveryContextCleanup::create(T *x,
CrashRecoveryContextCleanup::ProvidedCleanups cleanupKind) {
return CrashRecoveryContext::GetCurrent() ?
CrashRecoveryContextTrait<T>::createCleanup(x, cleanupKind) :
0;
}
template <typename T>
class CrashRecoveryContextDestructorCleanup : public
CrashRecoveryContextCleanupBase<CrashRecoveryContextDestructorCleanup<T>, T> {
public:
CrashRecoveryContextDestructorCleanup(CrashRecoveryContext *context,
T *resource)
: 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 {
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);
}
};
}