mirror of
https://github.com/matrix-construct/construct
synced 2024-11-16 23:10:54 +01:00
125 lines
2.8 KiB
C++
125 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
|