#include #include "components/taskqueue.hpp" #include "utils/factory.hpp" POLYBAR_NS taskqueue::make_type taskqueue::make() { return factory_util::unique(); } taskqueue::taskqueue() { m_thread = std::thread([&] { while (m_active) { std::unique_lock guard(m_lock); if (m_deferred.empty()) { m_hold.wait(guard); } else { auto now = deferred::clock::now(); auto wait = m_deferred.front()->now + m_deferred.front()->wait; for (auto&& task : m_deferred) { auto when = task->now + task->wait; if (when < wait) { wait = move(when); } } if (wait > now) { m_hold.wait_for(guard, wait - now); } } if (!m_deferred.empty()) { guard.unlock(); tick(); } } }); } taskqueue::~taskqueue() { if (m_active && m_thread.joinable()) { m_active = false; m_hold.notify_all(); m_thread.join(); } } void taskqueue::defer( string id, deferred::duration ms, deferred::callback fn, deferred::duration offset, size_t count) { std::unique_lock guard(m_lock); deferred::timepoint now{chrono::time_point_cast(deferred::clock::now() + move(offset))}; m_deferred.emplace_back(make_unique(move(id), move(now), move(ms), move(fn), move(count))); guard.unlock(); m_hold.notify_one(); } void taskqueue::defer_unique( string id, deferred::duration ms, deferred::callback fn, deferred::duration offset, size_t count) { purge(id); std::unique_lock guard(m_lock); deferred::timepoint now{chrono::time_point_cast(deferred::clock::now() + move(offset))}; m_deferred.emplace_back(make_unique(move(id), move(now), move(ms), move(fn), move(count))); guard.unlock(); m_hold.notify_one(); } void taskqueue::tick() { if (!m_lock.try_lock()) { return; } std::unique_lock guard(m_lock, std::adopt_lock); auto now = chrono::time_point_cast(deferred::clock::now()); vector> cbs; for (auto it = m_deferred.rbegin(); it != m_deferred.rend(); ++it) { auto& task = *it; if (task->now + task->wait > now) { continue; } else if (task->count--) { cbs.emplace_back(make_pair(task->func, task->count)); task->now = now; } else { m_deferred.erase(std::remove_if(m_deferred.begin(), m_deferred.end(), [&](const unique_ptr& d) { return d == task; }), m_deferred.end()); } } guard.unlock(); for (auto&& p : cbs) { p.first(p.second); } } bool taskqueue::purge(const string& id) { std::lock_guard guard(m_lock); return m_deferred.erase(std::remove_if(m_deferred.begin(), m_deferred.end(), [id](const unique_ptr& d) { return d->id == id; }), m_deferred.end()) == m_deferred.end(); } bool taskqueue::exist(const string& id) { std::lock_guard guard(m_lock); for (const auto& task : m_deferred) { if (task->id == id) { return true; } } return false; } POLYBAR_NS_END