/* * Copyright (c) 2019-2020, Sergey Bugaev * Copyright (c) 2021, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include namespace Threading { template class BackgroundAction; class BackgroundActionBase { template friend class BackgroundAction; private: BackgroundActionBase() { } static void enqueue_work(Function); static Thread& background_thread(); }; template class BackgroundAction final : public Core::Object , private BackgroundActionBase { C_OBJECT(BackgroundAction); public: void cancel() { m_cancelled = true; } bool is_cancelled() const { return m_cancelled; } virtual ~BackgroundAction() { } private: BackgroundAction(Function action, Function on_complete) : Core::Object(&background_thread()) , m_action(move(action)) , m_on_complete(move(on_complete)) { enqueue_work([this, origin_event_loop = &Core::EventLoop::current()] { m_result = m_action(*this); if (m_on_complete) { origin_event_loop->deferred_invoke([this] { m_on_complete(m_result.release_value()); remove_from_parent(); }); origin_event_loop->wake(); } else { this->remove_from_parent(); } }); } bool m_cancelled { false }; Function m_action; Function m_on_complete; Optional m_result; }; }