construct/ircd/ctx_eh.cc

126 lines
2.8 KiB
C++

// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2019 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
#include <RB_INC_CXXABI_H
#include "ctx.h"
#ifdef HAVE_CXXABI_H
struct __cxxabiv1::__cxa_eh_globals
{
__cxa_exception *caughtExceptions;
unsigned int uncaughtExceptions;
};
#endif
//
// exception_handler
//
ircd::ctx::exception_handler::exception_handler()
noexcept
:std::exception_ptr
{
// capture a shared reference of the current exception before the catch
// block closes around it.
std::current_exception()
}
{
assert(bool(*this));
// close the catch block.
end_catch();
// We don't yet support more levels of exceptions; after ending this
// catch we can't still be in another one. This doesn't apply if we're
// not on any ctx currently.
assert(!current || !std::uncaught_exceptions());
}
//
// util
//
#ifdef HAVE_CXXABI_H
void
ircd::ctx::exception_handler::end_catch()
noexcept
{
// Only close the catch block if we're actually on an ircd::ctx. This
// allows the same codepath with a ctx::exception_handler to be used
// outside of the ircd::ctx system to not incur any unexpected or
// potential issues with ending the catch manually.
if(likely(current))
__cxxabiv1::__cxa_end_catch();
}
#else
#warning "CXXABI not available. Context switch inside catch block may be unsafe!"
void
ircd::ctx::exception_handler::end_catch()
noexcept
{
}
#endif
#ifdef HAVE_CXXABI_H
/// Get the uncaught exception count
uint
ircd::ctx::exception_handler::uncaught_exceptions()
noexcept
{
const auto &cxa_globals
{
__cxxabiv1::__cxa_get_globals_fast()
};
assert(cxa_globals);
return cxa_globals->uncaughtExceptions;
}
#else
#warning "CXXABI not available. Context switch with uncaught exceptions may be unsafe!"
uint
ircd::ctx::exception_handler::uncaught_exceptions()
noexcept
{
return std::uncaught_exceptions();
}
#endif
#ifdef HAVE_CXXABI_H
/// Set the uncaught exception count and return the previous value.
uint
ircd::ctx::exception_handler::uncaught_exceptions(const uint &val)
noexcept
{
const auto &cxa_globals
{
__cxxabiv1::__cxa_get_globals_fast()
};
assert(cxa_globals);
const auto ret
{
cxa_globals->uncaughtExceptions
};
assert(unsigned(ret) == unsigned(std::uncaught_exceptions()));
cxa_globals->uncaughtExceptions = val;
return ret;
}
#else
#warning "CXXABI not available. Context switch with uncaught exceptions may be unsafe!"
uint
ircd::ctx::exception_handler::uncaught_exceptions(const uint &val)
noexcept
{
assert(std::uncaught_exceptions() == val);
return std::uncaught_exceptions();
}
#endif