File indexing completed on 2024-05-05 16:47:05
0001 // SPDX-FileCopyrightText: 2021 Carson Black <uhhadd@gmail.com> 0002 // 0003 // SPDX-License-Identifier: MIT 0004 0005 #pragma once 0006 0007 #include "coroutine_integration.h" 0008 0009 #include <functional> 0010 #include <type_traits> 0011 0012 #define perform co_await 0013 0014 template<typename T> 0015 class Effect { 0016 struct Holder { 0017 T t; 0018 }; 0019 QSharedPointer<Holder> val; 0020 0021 public: 0022 Effect() { 0023 val.reset(new Holder); 0024 } 0025 Effect(const Effect& other) { 0026 val = other.val; 0027 } 0028 operator T() const { 0029 return val->t; 0030 } 0031 0032 struct promise_type { 0033 private: 0034 Effect<T> t; 0035 0036 public: 0037 promise_type() { 0038 t = Effect<T>{}; 0039 } 0040 0041 Effect<T> get_return_object() noexcept { 0042 return t; 0043 } 0044 0045 coroutine_namespace::suspend_never initial_suspend() const noexcept { return {}; } 0046 coroutine_namespace::suspend_never final_suspend() const noexcept { return {}; } 0047 0048 void return_value(const T& value) noexcept { 0049 t.val->t = value; 0050 } 0051 void return_value(T&& value) noexcept { 0052 t.val->t = std::move(value); 0053 } 0054 0055 void unhandled_exception() noexcept { 0056 Q_ASSERT("unhandled exception"); 0057 } 0058 }; 0059 }; 0060 0061 template<> 0062 class Effect<void> { 0063 }; 0064 0065 template<typename ...Args> 0066 struct coroutine_namespace::coroutine_traits<Effect<void>, Args...> 0067 { 0068 struct promise_type { 0069 private: 0070 Effect<void> t; 0071 0072 public: 0073 promise_type() { 0074 t = Effect<void>{}; 0075 } 0076 0077 Effect<void> get_return_object() noexcept { 0078 return t; 0079 } 0080 0081 coroutine_namespace::suspend_never initial_suspend() const noexcept { return {}; } 0082 coroutine_namespace::suspend_never final_suspend() const noexcept { return {}; } 0083 0084 void return_void() noexcept { 0085 } 0086 0087 void unhandled_exception() noexcept { 0088 Q_ASSERT("unhandled exception"); 0089 } 0090 }; 0091 }; 0092 0093 template<typename Fn> 0094 class EffectVoidFun { 0095 static thread_local QList<Fn> items; 0096 0097 public: 0098 0099 template<typename... Args> 0100 EffectVoidFun(Args&&... args) { 0101 items.last()(std::forward<Args>(args)...); 0102 } 0103 0104 static auto handler(Fn fn) { 0105 items << fn; 0106 struct Deleter { 0107 ~Deleter() { 0108 items.pop_back(); 0109 } 0110 }; 0111 return Deleter{}; 0112 } 0113 0114 bool await_ready() const noexcept { 0115 return true; 0116 } 0117 void await_suspend(coroutine_namespace::coroutine_handle<> cont) const { 0118 cont(); 0119 } 0120 void await_resume() { 0121 return; 0122 } 0123 }; 0124 0125 template<typename T> 0126 inline thread_local QList<T> EffectVoidFun<T>::items; 0127 0128 template<typename Fn> 0129 class EffectFun { 0130 static thread_local QList<Fn> items; 0131 typename Fn::result_type ret; 0132 0133 public: 0134 0135 template<typename... Args> 0136 EffectFun(Args&&... args) { 0137 ret = items.last()(std::forward<Args>(args)...); 0138 } 0139 0140 static auto handler(Fn fn) { 0141 items << fn; 0142 struct Deleter { 0143 ~Deleter() { 0144 items.pop_back(); 0145 } 0146 }; 0147 return Deleter{}; 0148 } 0149 0150 bool await_ready() const noexcept { 0151 return true; 0152 } 0153 void await_suspend(coroutine_namespace::coroutine_handle<> cont) const { 0154 cont(); 0155 } 0156 typename Fn::result_type await_resume() { 0157 return ret; 0158 } 0159 }; 0160 0161 template<typename T> 0162 inline thread_local QList<T> EffectFun<T>::items;