浏览代码

Merge pull request #9034 from liamwhite/result-macros

kernel: add expanded result macros
bunnei 3 年之前
父节点
当前提交
64c2ccb0cb
共有 1 个文件被更改,包括 114 次插入6 次删除
  1. 114 6
      src/core/hle/result.h

+ 114 - 6
src/core/hle/result.h

@@ -5,6 +5,7 @@
 
 #include "common/assert.h"
 #include "common/bit_field.h"
+#include "common/common_funcs.h"
 #include "common/common_types.h"
 #include "common/expected.h"
 
@@ -130,6 +131,10 @@ union Result {
     [[nodiscard]] constexpr bool IsError() const {
         return !IsSuccess();
     }
+
+    [[nodiscard]] constexpr bool IsFailure() const {
+        return !IsSuccess();
+    }
 };
 static_assert(std::is_trivial_v<Result>);
 
@@ -349,10 +354,110 @@ private:
         }                                                                                          \
     } while (false)
 
-#define R_SUCCEEDED(res) (res.IsSuccess())
+#define R_SUCCEEDED(res) (static_cast<Result>(res).IsSuccess())
+#define R_FAILED(res) (static_cast<Result>(res).IsFailure())
 
-/// Evaluates a boolean expression, and succeeds if that expression is true.
-#define R_SUCCEED_IF(expr) R_UNLESS(!(expr), ResultSuccess)
+namespace ResultImpl {
+template <auto EvaluateResult, class F>
+class ScopedResultGuard {
+    YUZU_NON_COPYABLE(ScopedResultGuard);
+    YUZU_NON_MOVEABLE(ScopedResultGuard);
+
+private:
+    Result& m_ref;
+    F m_f;
+
+public:
+    constexpr ScopedResultGuard(Result& ref, F f) : m_ref(ref), m_f(std::move(f)) {}
+    constexpr ~ScopedResultGuard() {
+        if (EvaluateResult(m_ref)) {
+            m_f();
+        }
+    }
+};
+
+template <auto EvaluateResult>
+class ResultReferenceForScopedResultGuard {
+private:
+    Result& m_ref;
+
+public:
+    constexpr ResultReferenceForScopedResultGuard(Result& r) : m_ref(r) {}
+    constexpr operator Result&() const {
+        return m_ref;
+    }
+};
+
+template <auto EvaluateResult, typename F>
+constexpr ScopedResultGuard<EvaluateResult, F> operator+(
+    ResultReferenceForScopedResultGuard<EvaluateResult> ref, F&& f) {
+    return ScopedResultGuard<EvaluateResult, F>(static_cast<Result&>(ref), std::forward<F>(f));
+}
+
+constexpr bool EvaluateResultSuccess(const Result& r) {
+    return R_SUCCEEDED(r);
+}
+constexpr bool EvaluateResultFailure(const Result& r) {
+    return R_FAILED(r);
+}
+
+template <typename T>
+constexpr void UpdateCurrentResultReference(T result_reference, Result result) {
+    ASSERT(false);
+}
+
+template <>
+constexpr void UpdateCurrentResultReference<Result&>(Result& result_reference, Result result) {
+    result_reference = result;
+}
+
+template <>
+constexpr void UpdateCurrentResultReference<Result>(Result result_reference, Result result) {}
+} // namespace ResultImpl
+
+#define DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(COUNTER_VALUE)                                \
+    [[maybe_unused]] constexpr bool HasPrevRef_##COUNTER_VALUE =                                   \
+        std::same_as<decltype(__TmpCurrentResultReference), Result&>;                              \
+    [[maybe_unused]] auto& PrevRef_##COUNTER_VALUE = __TmpCurrentResultReference;                  \
+    [[maybe_unused]] Result __tmp_result_##COUNTER_VALUE = ResultSuccess;                          \
+    Result& __TmpCurrentResultReference =                                                          \
+        HasPrevRef_##COUNTER_VALUE ? PrevRef_##COUNTER_VALUE : __tmp_result_##COUNTER_VALUE
+
+#define ON_RESULT_RETURN_IMPL(...)                                                                 \
+    static_assert(std::same_as<decltype(__TmpCurrentResultReference), Result&>);                   \
+    auto RESULT_GUARD_STATE_##__COUNTER__ =                                                        \
+        ResultImpl::ResultReferenceForScopedResultGuard<__VA_ARGS__>(                              \
+            __TmpCurrentResultReference) +                                                         \
+        [&]()
+
+#define ON_RESULT_FAILURE_2 ON_RESULT_RETURN_IMPL(ResultImpl::EvaluateResultFailure)
+
+#define ON_RESULT_FAILURE                                                                          \
+    DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(__COUNTER__);                                     \
+    ON_RESULT_FAILURE_2
+
+#define ON_RESULT_SUCCESS_2 ON_RESULT_RETURN_IMPL(ResultImpl::EvaluateResultSuccess)
+
+#define ON_RESULT_SUCCESS                                                                          \
+    DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(__COUNTER__);                                     \
+    ON_RESULT_SUCCESS_2
+
+constexpr inline Result __TmpCurrentResultReference = ResultSuccess;
+
+/// Returns a result.
+#define R_RETURN(res_expr)                                                                         \
+    {                                                                                              \
+        const Result _tmp_r_throw_rc = (res_expr);                                                 \
+        ResultImpl::UpdateCurrentResultReference<decltype(__TmpCurrentResultReference)>(           \
+            __TmpCurrentResultReference, _tmp_r_throw_rc);                                         \
+        return _tmp_r_throw_rc;                                                                    \
+    }
+
+/// Returns ResultSuccess()
+#define R_SUCCEED() R_RETURN(ResultSuccess)
+
+/// Throws a result.
+#define R_THROW(res_expr) R_RETURN(res_expr)
 
 /// Evaluates a boolean expression, and returns a result unless that expression is true.
 #define R_UNLESS(expr, res)                                                                        \
@@ -361,7 +466,7 @@ private:
             if (res.IsError()) {                                                                   \
                 LOG_ERROR(Kernel, "Failed with result: {}", res.raw);                              \
             }                                                                                      \
-            return res;                                                                            \
+            R_THROW(res);                                                                          \
         }                                                                                          \
     }
 
@@ -369,7 +474,10 @@ private:
 #define R_TRY(res_expr)                                                                            \
     {                                                                                              \
         const auto _tmp_r_try_rc = (res_expr);                                                     \
-        if (_tmp_r_try_rc.IsError()) {                                                             \
-            return _tmp_r_try_rc;                                                                  \
+        if (R_FAILED(_tmp_r_try_rc)) {                                                             \
+            R_THROW(_tmp_r_try_rc);                                                                \
         }                                                                                          \
     }
+
+/// Evaluates a boolean expression, and succeeds if that expression is true.
+#define R_SUCCEED_IF(expr) R_UNLESS(!(expr), ResultSuccess)