#pragma once #include #include #include #include namespace tl { class async_queue { public: using Item = function; void enqueue(Item func) noexcept { std::lock_guard lg(m_mutex); m_items.push_back(std::move(func)); } bool run_one() noexcept { std::unique_lock lg(m_mutex); if (m_items.empty()) return false; const Item item = std::move(m_items.front()); m_items.pop_front(); lg.unlock(); item(); return true; } bool run() noexcept { std::unique_lock lg(m_mutex); if (m_items.empty()) return false; do { Item item = std::move(m_items.front()); m_items.pop_front(); lg.unlock(); item(); lg.lock(); } while (!m_items.empty()); return true; } private: std::mutex m_mutex; deque m_items; }; template std::future async(async_queue& queue, Func&& func) noexcept { shared_ptr> promise = make_shared>(); auto future = promise->get_future(); queue.enqueue([promise = std::move(promise), func = std::move(func)]() { if constexpr (tl::is_same_v) { func(); promise->set_value(); } else promise->set_value(func()); }); return future; } template bool is_ready(std::future const& f) noexcept { return f.valid() && f.wait_until(std::chrono::system_clock::time_point::min()) == std::future_status::ready; } }