Index: source/ps/Future.h =================================================================== --- source/ps/Future.h +++ source/ps/Future.h @@ -19,11 +19,13 @@ #define INCLUDED_FUTURE #include "ps/FutureForward.h" +#include "ps/Util.h" #include #include #include #include +#include #include template @@ -39,41 +41,12 @@ CANCELED }; -template -class SharedStateResult -{ -public: - void ResetResult() - { - if (m_HasResult) - m_Result.m_Result.~ResultType(); - m_HasResult = false; - } - - union Result - { - std::aligned_storage_t m_Bytes; - ResultType m_Result; - Result() : m_Bytes() {}; - ~Result() {}; - }; - // We don't use Result directly so the result doesn't have to be default constructible. - Result m_Result; - bool m_HasResult = false; -}; - -// Don't have m_Result for void ReturnType -template<> -class SharedStateResult -{ -}; - /** * The shared state between futures and packaged state. * Holds all relevant data. */ template -class SharedState : public SharedStateResult +class SharedState { static constexpr bool VoidResult = std::is_same_v; public: @@ -86,8 +59,6 @@ Wait(); Cancel(); } - if constexpr (!VoidResult) - SharedStateResult::ResetResult(); } SharedState(const SharedState&) = delete; @@ -121,8 +92,7 @@ { if (m_Status == Status::DONE) m_Status = Status::CANCELED; - if constexpr (!VoidResult) - SharedStateResult::ResetResult(); + m_Result.reset(); m_ConditionVariable.notify_all(); return cancelled; } @@ -136,16 +106,18 @@ std::enable_if_t, ResultType> GetResult() { // The caller must ensure that this is only called if we have a result. - ENSURE(SharedStateResult::m_HasResult); + ENSURE(m_Result.has_value()); m_Status = Status::CANCELED; - SharedStateResult::m_HasResult = false; - return std::move(SharedStateResult::m_Result.m_Result); + ResultType ret = std::move(*m_Result); + m_Result.reset(); + return ret; } std::atomic m_Status = Status::PENDING; std::mutex m_Mutex; std::condition_variable m_ConditionVariable; + std::optional> m_Result; std::function m_Func; }; @@ -281,13 +253,12 @@ return; if constexpr (VoidResult) - m_SharedState->m_Func(); - else { - // To avoid UB, explicitly placement-new the value. - new (&m_SharedState->m_Result) ResultType{std::move(m_SharedState->m_Func())}; - m_SharedState->m_HasResult = true; + m_SharedState->m_Func(); + m_SharedState->m_Result.emplace(); } + else + m_SharedState->m_Result.emplace(m_SharedState->m_Func()); // Because we might have threads waiting on us, we need to make sure that they either: // - don't wait on our condition variable Index: source/ps/Util.h =================================================================== --- source/ps/Util.h +++ source/ps/Util.h @@ -23,6 +23,8 @@ #include "lib/status.h" #include "ps/CStr.h" +#include + class Tex; void WriteSystemInfo(); @@ -38,4 +40,9 @@ std::string Hexify(const std::string& s); std::string Hexify(const u8* s, size_t length); +class VoidTag{}; + +template +using HandleVoid = std::conditional_t, VoidTag, T>; + #endif // PS_UTIL_H