/* * mptOSException.h * ---------------- * Purpose: platform-specific exception/signal handling * Notes : (currently none) * Authors: OpenMPT Devs * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. */ #pragma once #include "BuildSettings.h" #include "mptBaseMacros.h" #include "mptBaseTypes.h" #if defined(MODPLUG_TRACKER) #if MPT_OS_WINDOWS #include #endif // MPT_OS_WINDOWS #endif // MODPLUG_TRACKER OPENMPT_NAMESPACE_BEGIN #if defined(MODPLUG_TRACKER) #if MPT_OS_WINDOWS namespace Windows { namespace SEH { struct Code { private: DWORD m_Code; public: constexpr Code(DWORD code) noexcept : m_Code(code) { return; } public: constexpr DWORD code() const noexcept { return m_Code; } }; template auto TryFilterHandleThrow(const Tfn &fn, const Tfilter &filter, const Thandler &handler) -> decltype(fn()) { static_assert(std::is_trivially_copy_assignable::value); static_assert(std::is_trivially_copy_constructible::value); static_assert(std::is_trivially_move_assignable::value); static_assert(std::is_trivially_move_constructible::value); DWORD code = 0; __try { return fn(); } __except(filter(GetExceptionCode(), GetExceptionInformation())) { code = GetExceptionCode(); } throw Windows::SEH::Code(code); } template void TryFilterHandleVoid(const Tfn &fn, const Tfilter &filter, const Thandler &handler) { static_assert(std::is_same::value || std::is_trivially_copy_assignable::value); static_assert(std::is_same::value || std::is_trivially_copy_constructible::value); static_assert(std::is_same::value || std::is_trivially_move_assignable::value); static_assert(std::is_same::value || std::is_trivially_move_constructible::value); __try { fn(); return; } __except(filter(GetExceptionCode(), GetExceptionInformation())) { DWORD code = GetExceptionCode(); handler(code); } return; } template auto TryFilterHandleDefault(const Tfn &fn, const Tfilter &filter, const Thandler &handler, decltype(fn()) def = decltype(fn()){}) -> decltype(fn()) { static_assert(std::is_trivially_copy_assignable::value); static_assert(std::is_trivially_copy_constructible::value); static_assert(std::is_trivially_move_assignable::value); static_assert(std::is_trivially_move_constructible::value); auto result = def; __try { result = fn(); } __except(filter(GetExceptionCode(), GetExceptionInformation())) { DWORD code = GetExceptionCode(); result = handler(code); } return result; } template auto TryReturnOrThrow(const Tfn &fn) -> decltype(fn()) { return TryFilterHandleThrow( fn, [](auto code, auto eptr) { MPT_UNREFERENCED_PARAMETER(code); MPT_UNREFERENCED_PARAMETER(eptr); return EXCEPTION_EXECUTE_HANDLER; }, [](auto code) { throw Windows::SEH::Code(code); }); } template DWORD TryOrError(const Tfn &fn) { DWORD result = DWORD{0}; TryFilterHandleVoid( fn, [](auto code, auto eptr) { MPT_UNREFERENCED_PARAMETER(code); MPT_UNREFERENCED_PARAMETER(eptr); return EXCEPTION_EXECUTE_HANDLER; }, [&result](auto code) { result = code; }); return result; } template auto TryReturnOrDefault(const Tfn &fn, decltype(fn()) def = decltype(fn()){}) -> decltype(fn()) { return TryFilterHandleDefault( fn, [](auto code, auto eptr) { MPT_UNREFERENCED_PARAMETER(code); MPT_UNREFERENCED_PARAMETER(eptr); return EXCEPTION_EXECUTE_HANDLER; }, [def](auto code) { MPT_UNREFERENCED_PARAMETER(code); return def; }); } } // namspace SEH } // namespace Windows #endif // MPT_OS_WINDOWS #endif // MODPLUG_TRACKER OPENMPT_NAMESPACE_END