mptOSException.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * mptOSException.h
  3. * ----------------
  4. * Purpose: platform-specific exception/signal handling
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #pragma once
  10. #include "openmpt/all/BuildSettings.hpp"
  11. #include "mptBaseMacros.h"
  12. #include "mptBaseTypes.h"
  13. #if MPT_OS_WINDOWS
  14. #include <windows.h>
  15. #endif // MPT_OS_WINDOWS
  16. OPENMPT_NAMESPACE_BEGIN
  17. #if MPT_OS_WINDOWS
  18. namespace Windows
  19. {
  20. namespace SEH
  21. {
  22. struct Code
  23. {
  24. private:
  25. DWORD m_Code;
  26. public:
  27. constexpr Code(DWORD code) noexcept
  28. : m_Code(code)
  29. {
  30. return;
  31. }
  32. public:
  33. constexpr DWORD code() const noexcept
  34. {
  35. return m_Code;
  36. }
  37. };
  38. template <typename Tfn, typename Tfilter, typename Thandler>
  39. auto TryFilterHandleThrow(const Tfn &fn, const Tfilter &filter, const Thandler &handler) -> decltype(fn())
  40. {
  41. static_assert(std::is_trivially_copy_assignable<decltype(fn())>::value);
  42. static_assert(std::is_trivially_copy_constructible<decltype(fn())>::value);
  43. static_assert(std::is_trivially_move_assignable<decltype(fn())>::value);
  44. static_assert(std::is_trivially_move_constructible<decltype(fn())>::value);
  45. DWORD code = 0;
  46. __try
  47. {
  48. return fn();
  49. } __except(filter(GetExceptionCode(), GetExceptionInformation()))
  50. {
  51. code = GetExceptionCode();
  52. }
  53. throw Windows::SEH::Code(code);
  54. }
  55. template <typename Tfn, typename Tfilter, typename Thandler>
  56. void TryFilterHandleVoid(const Tfn &fn, const Tfilter &filter, const Thandler &handler)
  57. {
  58. static_assert(std::is_same<decltype(fn()), void>::value || std::is_trivially_copy_assignable<decltype(fn())>::value);
  59. static_assert(std::is_same<decltype(fn()), void>::value || std::is_trivially_copy_constructible<decltype(fn())>::value);
  60. static_assert(std::is_same<decltype(fn()), void>::value || std::is_trivially_move_assignable<decltype(fn())>::value);
  61. static_assert(std::is_same<decltype(fn()), void>::value || std::is_trivially_move_constructible<decltype(fn())>::value);
  62. __try
  63. {
  64. fn();
  65. return;
  66. } __except(filter(GetExceptionCode(), GetExceptionInformation()))
  67. {
  68. DWORD code = GetExceptionCode();
  69. handler(code);
  70. }
  71. return;
  72. }
  73. template <typename Tfn, typename Tfilter, typename Thandler>
  74. auto TryFilterHandleDefault(const Tfn &fn, const Tfilter &filter, const Thandler &handler, decltype(fn()) def = decltype(fn()){}) -> decltype(fn())
  75. {
  76. static_assert(std::is_trivially_copy_assignable<decltype(fn())>::value);
  77. static_assert(std::is_trivially_copy_constructible<decltype(fn())>::value);
  78. static_assert(std::is_trivially_move_assignable<decltype(fn())>::value);
  79. static_assert(std::is_trivially_move_constructible<decltype(fn())>::value);
  80. auto result = def;
  81. __try
  82. {
  83. result = fn();
  84. } __except(filter(GetExceptionCode(), GetExceptionInformation()))
  85. {
  86. DWORD code = GetExceptionCode();
  87. result = handler(code);
  88. }
  89. return result;
  90. }
  91. template <typename Tfn>
  92. auto TryReturnOrThrow(const Tfn &fn) -> decltype(fn())
  93. {
  94. return TryFilterHandleThrow(
  95. fn,
  96. [](auto code, auto eptr)
  97. {
  98. MPT_UNREFERENCED_PARAMETER(code);
  99. MPT_UNREFERENCED_PARAMETER(eptr);
  100. return EXCEPTION_EXECUTE_HANDLER;
  101. },
  102. [](auto code)
  103. {
  104. throw Windows::SEH::Code(code);
  105. });
  106. }
  107. template <typename Tfn>
  108. DWORD TryOrError(const Tfn &fn)
  109. {
  110. DWORD result = DWORD{0};
  111. TryFilterHandleVoid(
  112. fn,
  113. [](auto code, auto eptr)
  114. {
  115. MPT_UNREFERENCED_PARAMETER(code);
  116. MPT_UNREFERENCED_PARAMETER(eptr);
  117. return EXCEPTION_EXECUTE_HANDLER;
  118. },
  119. [&result](auto code)
  120. {
  121. result = code;
  122. });
  123. return result;
  124. }
  125. template <typename Tfn>
  126. auto TryReturnOrDefault(const Tfn &fn, decltype(fn()) def = decltype(fn()){}) -> decltype(fn())
  127. {
  128. return TryFilterHandleDefault(
  129. fn,
  130. [](auto code, auto eptr)
  131. {
  132. MPT_UNREFERENCED_PARAMETER(code);
  133. MPT_UNREFERENCED_PARAMETER(eptr);
  134. return EXCEPTION_EXECUTE_HANDLER;
  135. },
  136. [def](auto code)
  137. {
  138. MPT_UNREFERENCED_PARAMETER(code);
  139. return def;
  140. });
  141. }
  142. } // namspace SEH
  143. } // namespace Windows
  144. #endif // MPT_OS_WINDOWS
  145. OPENMPT_NAMESPACE_END