88 lines
1.5 KiB
C++
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;
|
|
}
|
|
|
|
} |