/* * Copyright 2020 Han Young * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "waittimerwakeupprovider.h" WaitTimerWakeupProvider::WaitTimerWakeupProvider(QObject *parent) : AbstractWakeupProvider(parent) , m_timerThread(nullptr) , m_cookie(1) , m_worker(nullptr) { initWorker(); } WaitTimerWakeupProvider::~WaitTimerWakeupProvider() { if (m_worker) { m_worker->deleteLater(); } } int WaitTimerWakeupProvider::scheduleWakeup(quint64 timestamp) { m_waitWorkerCookies.append({++m_cookie, timestamp}); schedule(); return m_cookie; } void WaitTimerWakeupProvider::clearWakeup(int cookie) { for (auto index = m_waitWorkerCookies.begin(); index < m_waitWorkerCookies.end(); ++index) { int pairCookie = (*index).first; if (cookie == pairCookie) { m_waitWorkerCookies.erase(index); } } // ensure that we schedule the next queued wakeup schedule(); } void WaitTimerWakeupProvider::schedule() { if (!m_worker) { return; } auto eternity = std::numeric_limits::max(); auto minTime = eternity; for (auto tuple : m_waitWorkerCookies) { if (minTime > tuple.second) { minTime = tuple.second; m_currentCookie = tuple.first; } } if (minTime != eternity) { // only schedule worker if we have something to wait on m_worker->setNewTime(minTime); // Unix uses int64 internally for time } } void WaitTimerWakeupProvider::initWorker() { if (!m_timerThread) { m_timerThread = new QThread(); m_worker = new AlarmWaitWorker(); m_worker->moveToThread(m_timerThread); connect(m_worker, &AlarmWaitWorker::finished, this, [this] { // notify time is up Q_EMIT wakeup(m_currentCookie); clearWakeup(m_currentCookie); }); } m_timerThread->start(); }