Index: source/graphics/MapReader.cpp =================================================================== --- source/graphics/MapReader.cpp +++ source/graphics/MapReader.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -1331,11 +1331,6 @@ { std::atomic progress{1}; Future task; - - ~GeneratorState() - { - task.CancelOrWait(); - } }; int CMapReader::StartMapGeneration(const CStrW& scriptFile) Index: source/graphics/TextureConverter.cpp =================================================================== --- source/graphics/TextureConverter.cpp +++ source/graphics/TextureConverter.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -311,16 +311,7 @@ #endif // CONFIG2_NVTT } -CTextureConverter::~CTextureConverter() -{ -#if CONFIG2_NVTT - while (!m_ResultQueue.empty()) - { - m_ResultQueue.front().CancelOrWait(); - m_ResultQueue.pop(); - } -#endif // CONFIG2_NVTT -} +CTextureConverter::~CTextureConverter() = default; bool CTextureConverter::ConvertTexture(const CTexturePtr& texture, const VfsPath& src, const VfsPath& dest, const Settings& settings) { Index: source/ps/Future.h =================================================================== --- source/ps/Future.h +++ source/ps/Future.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -44,8 +44,7 @@ using ResultHolder = std::conditional_t, std::nullopt_t, std::optional>; /** - * The shared state between futures and packaged state. - * Holds all relevant data. + * Responsible for syncronization between the task and the receiving thread. */ template class Receiver : public ResultHolder @@ -57,12 +56,7 @@ {} ~Receiver() { - // For safety, wait on started task completion, but not on pending ones (auto-cancelled). - if (!Cancel()) - { - Wait(); - Cancel(); - } + ENSURE(IsDoneOrCanceled()); } Receiver(const Receiver&) = delete; @@ -123,6 +117,9 @@ std::condition_variable m_ConditionVariable; }; +/** + * The shared state between futures and packaged state. + */ template struct SharedState { @@ -145,7 +142,7 @@ * * Future is _not_ thread-safe. Call it from a single thread or ensure synchronization externally. * - * The destructor is never blocking. The promise may still be running on destruction. + * The callback never runs after the @p Future is destroyed. * TODO: * - Handle exceptions. */ @@ -162,11 +159,19 @@ Future() = default; Future(const Future& o) = delete; Future(Future&&) = default; - Future& operator=(Future&&) = default; - ~Future() = default; + Future& operator=(Future&& other) + { + CancelOrWait(); + m_Receiver = std::move(other.m_Receiver); + return *this; + } + ~Future() + { + CancelOrWait(); + } /** - * Make the future wait for the result of @a func. + * Make the future wait for the result of @a callback. */ template PackagedTask Wrap(Callback&& callback); @@ -293,6 +298,7 @@ { static_assert(std::is_same_v, ResultType>, "The return type of the wrapped function is not the same as the type the Future expects."); + CancelOrWait(); auto temp = std::make_shared>(std::move(callback)); m_Receiver = {temp, &temp->receiver}; return PackagedTask(std::move(temp)); Index: source/ps/tests/test_Future.h =================================================================== --- source/ps/tests/test_Future.h +++ source/ps/tests/test_Future.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -27,22 +27,11 @@ public: void test_future_basic() { - int counter = 0; - { - Future noret; - std::function task = noret.Wrap([&counter]() mutable { counter++; }); - task(); - TS_ASSERT_EQUALS(counter, 1); - } - - { - Future noret; - { - std::function task = noret.Wrap([&counter]() mutable { counter++; }); - // Auto-cancels the task. - } - } - TS_ASSERT_EQUALS(counter, 1); + bool executed{false}; + Future noret; + auto task = noret.Wrap([&]{ executed = true; }); + task(); + TS_ASSERT(executed); } void test_future_return() Index: source/simulation2/components/CCmpPathfinder.cpp =================================================================== --- source/simulation2/components/CCmpPathfinder.cpp +++ source/simulation2/components/CCmpPathfinder.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -105,9 +105,6 @@ { SetDebugOverlay(false); // cleans up memory - // Wait on all pathfinding tasks. - for (Future& future : m_Futures) - future.CancelOrWait(); m_Futures.clear(); SAFE_DELETE(m_AtlasOverlay);