/* * 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: static NonnullRefPtr> create( Function action, Function on_complete = nullptr) { return adopt_ref(*new BackgroundAction(move(action), move(on_complete))); } 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] { m_result = m_action(*this); if (m_on_complete) { Core::EventLoop::current().post_event(*this, make([this](auto&) { m_on_complete(m_result.release_value()); this->remove_from_parent(); })); Core::EventLoop::wake(); } else { this->remove_from_parent(); } }); } bool m_cancelled { false }; Function m_action; Function m_on_complete; Optional m_result; }; }