#pragma once #include #include #include #include #include #include #include #include namespace LibThread { template class BackgroundAction; class BackgroundActionBase { template friend class BackgroundAction; private: BackgroundActionBase() {} static Lockable>>& all_actions(); static Thread& background_thread(); }; template class BackgroundAction final : public CObject , private BackgroundActionBase { C_OBJECT(BackgroundAction); public: static NonnullRefPtr> create( Function action, Function on_complete = nullptr ) { return adopt(*new BackgroundAction(move(action), move(on_complete))); } virtual ~BackgroundAction() {} private: BackgroundAction(Function action, Function on_complete) : CObject(&background_thread()) , m_action(move(action)) , m_on_complete(move(on_complete)) { LOCKER(all_actions().lock()); this->ref(); all_actions().resource().enqueue([this] { m_result = m_action(); if (m_on_complete) { CEventLoop::main().post_event(*this, make([this](CObject&) { m_on_complete(m_result.release_value()); this->deref(); })); CEventLoop::main().wake(); } else this->deref(); }); } Function m_action; Function m_on_complete; Optional m_result; }; }