Files
TL/include/tl/async_queue.h
jeanlemotan 8297b0b45f First
2024-07-02 18:06:33 +02:00

88 lines
1.5 KiB
C++

#pragma once
#include <mutex>
#include <future>
#include <tl/deque.h>
#include <tl/functional.h>
namespace tl
{
class async_queue
{
public:
using Item = function<void()>;
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<Item> m_items;
};
template<typename Res, typename Func>
std::future<Res> async(async_queue& queue, Func&& func) noexcept
{
shared_ptr<std::promise<Res>> promise = make_shared<std::promise<Res>>();
auto future = promise->get_future();
queue.enqueue([promise = std::move(promise), func = std::move(func)]()
{
if constexpr (tl::is_same_v<Res, void>)
{
func();
promise->set_value();
}
else
promise->set_value(func());
});
return future;
}
template<typename R>
bool is_ready(std::future<R> const& f) noexcept
{
return f.valid() && f.wait_until(std::chrono::system_clock::time_point::min()) == std::future_status::ready;
}
}