mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-13 00:10:37 +00:00
Augment CrashRecoveryContext to have registered "cleanup" objects that can be used to release resources during a crash.
llvm-svn: 127849
This commit is contained in:
parent
6a874d7f22
commit
1a2fa05e5f
@ -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();
|
||||
@ -87,6 +93,64 @@ public:
|
||||
const std::string &getBacktrace() const;
|
||||
};
|
||||
|
||||
class CrashRecoveryContextCleanup {
|
||||
public:
|
||||
virtual ~CrashRecoveryContextCleanup();
|
||||
virtual void recoverResources() = 0;
|
||||
|
||||
template <typename T> static CrashRecoveryContextCleanup *create(T *);
|
||||
|
||||
private:
|
||||
friend class CrashRecoveryContext;
|
||||
CrashRecoveryContextCleanup *prev, *next;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class CrashRecoveryContextDestructorCleanup
|
||||
: public CrashRecoveryContextCleanup
|
||||
{
|
||||
T *resource;
|
||||
public:
|
||||
CrashRecoveryContextDestructorCleanup(T *resource) : resource(resource) {}
|
||||
virtual void recoverResources() {
|
||||
resource->~T();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct CrashRecoveryContextTrait {
|
||||
static inline CrashRecoveryContextCleanup *createCleanup(T *resource) {
|
||||
return new CrashRecoveryContextDestructorCleanup<T>(resource);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline CrashRecoveryContextCleanup* CrashRecoveryContextCleanup::create(T *x) {
|
||||
return CrashRecoveryContext::GetCurrent() ?
|
||||
CrashRecoveryContextTrait<T>::createCleanup(x) :
|
||||
0;
|
||||
}
|
||||
|
||||
class CrashRecoveryContextCleanupRegistrar {
|
||||
CrashRecoveryContext *context;
|
||||
CrashRecoveryContextCleanup *cleanup;
|
||||
public:
|
||||
CrashRecoveryContextCleanupRegistrar(CrashRecoveryContextCleanup *cleanup)
|
||||
: context(CrashRecoveryContext::GetCurrent()),
|
||||
cleanup(cleanup)
|
||||
{
|
||||
if (context && cleanup)
|
||||
context->registerCleanup(cleanup);
|
||||
}
|
||||
~CrashRecoveryContextCleanupRegistrar() {
|
||||
if (cleanup) {
|
||||
if (context)
|
||||
context->unregisterCleanup(cleanup);
|
||||
else
|
||||
delete cleanup;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -57,7 +57,18 @@ public:
|
||||
static sys::Mutex gCrashRecoveryContexMutex;
|
||||
static bool gCrashRecoveryEnabled = false;
|
||||
|
||||
CrashRecoveryContextCleanup::~CrashRecoveryContextCleanup() {}
|
||||
|
||||
CrashRecoveryContext::~CrashRecoveryContext() {
|
||||
// Reclaim registered resources.
|
||||
CrashRecoveryContextCleanup *i = head;
|
||||
while (i) {
|
||||
CrashRecoveryContextCleanup *tmp = i;
|
||||
i = tmp->next;
|
||||
tmp->recoverResources();
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
|
||||
delete CRCI;
|
||||
}
|
||||
@ -70,6 +81,33 @@ CrashRecoveryContext *CrashRecoveryContext::GetCurrent() {
|
||||
return CRCI->CRC;
|
||||
}
|
||||
|
||||
void CrashRecoveryContext::registerCleanup(CrashRecoveryContextCleanup *cleanup)
|
||||
{
|
||||
if (!cleanup)
|
||||
return;
|
||||
if (head)
|
||||
head->prev = cleanup;
|
||||
cleanup->next = head;
|
||||
head = cleanup;
|
||||
}
|
||||
|
||||
void
|
||||
CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) {
|
||||
if (!cleanup)
|
||||
return;
|
||||
if (cleanup == head) {
|
||||
head = cleanup->next;
|
||||
if (head)
|
||||
head->prev = 0;
|
||||
}
|
||||
else {
|
||||
cleanup->prev->next = cleanup->next;
|
||||
if (cleanup->next)
|
||||
cleanup->next->prev = cleanup->prev;
|
||||
}
|
||||
delete cleanup;
|
||||
}
|
||||
|
||||
#ifdef LLVM_ON_WIN32
|
||||
|
||||
// FIXME: No real Win32 implementation currently.
|
||||
|
Loading…
x
Reference in New Issue
Block a user