From a396e6af3cd16530202f6cbecbd45c7a3f6ac893 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 24 Apr 2014 22:34:42 -0500 Subject: hw alarms --- src/alarm-queue-simple.cpp | 153 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 src/alarm-queue-simple.cpp (limited to 'src/alarm-queue-simple.cpp') diff --git a/src/alarm-queue-simple.cpp b/src/alarm-queue-simple.cpp new file mode 100644 index 0000000..2fd289c --- /dev/null +++ b/src/alarm-queue-simple.cpp @@ -0,0 +1,153 @@ +/* + * Copyright 2014 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include + +#include + +namespace unity { +namespace indicator { +namespace datetime { + +/*** +**** Public API +***/ + +SimpleAlarmQueue::SimpleAlarmQueue(const std::shared_ptr& clock, + const std::shared_ptr& planner, + const std::shared_ptr& timer): + m_clock(clock), + m_planner(planner), + m_timer(timer), + m_time(clock->localtime()) +{ + m_planner->appointments().changed().connect([this](const std::vector&){ + g_debug("AlarmQueue %p calling requeue() due to appointments changed", this); + requeue(); + }); + + m_clock->minute_changed.connect([=]{ + const auto now = m_clock->localtime(); + constexpr auto skew_threshold_usec = int64_t{90} * G_USEC_PER_SEC; + const bool clock_jumped = std::abs(now - m_time) > skew_threshold_usec; + m_time = now; + if (clock_jumped) { + g_message("AlarmQueue %p calling requeue() due to clock skew", this); + requeue(); + } + }); + + m_timer->timeout().connect([this](){ + g_message("AlarmQueue %p calling requeue() due to timeout", this); + requeue(); + }); + + requeue(); +} + +SimpleAlarmQueue::~SimpleAlarmQueue() +{ +} + +core::Signal& SimpleAlarmQueue::alarm_reached() +{ + return m_alarm_reached; +} + +/*** +**** +***/ + +void SimpleAlarmQueue::requeue() +{ + // kick any current alarms + for (auto current : find_current_alarms()) + { + m_triggered.insert(current.uid); + m_alarm_reached(current); + } + + // idle until the next alarm + Appointment next; + if (find_next_alarm(next)) + { + g_debug ("setting timer to wake up for next appointment '%s' at %s", + next.summary.c_str(), + next.begin.format("%F %T").c_str()); + + m_timer->set_wakeup_time(next.begin); + } +} + +// find the next alarm that will kick now or in the future +bool SimpleAlarmQueue::find_next_alarm(Appointment& setme) const +{ + bool found = false; + Appointment tmp; + const auto now = m_clock->localtime(); + const auto beginning_of_minute = now.add_full (0, 0, 0, 0, 0, -now.seconds()); + + for(const auto& walk : m_planner->appointments().get()) + { + if (m_triggered.count(walk.uid)) // did we already use this one? + continue; + + if (walk.begin < beginning_of_minute) // has this one already passed? + continue; + + if (found && (tmp.begin < walk.begin)) // do we already have a better match? + continue; + + tmp = walk; + found = true; + } + + if (found) + setme = tmp; + + return found; +} + +// find the alarm(s) that should kick right now +std::vector SimpleAlarmQueue::find_current_alarms() const +{ + std::vector appointments; + + const auto now = m_clock->localtime(); + + for(const auto& walk : m_planner->appointments().get()) + { + if (m_triggered.count(walk.uid)) // did we already use this one? + continue; + if (!DateTime::is_same_minute(now, walk.begin)) + continue; + + appointments.push_back(walk); + } + + return appointments; +} + +/*** +**** +***/ + +} // namespace datetime +} // namespace indicator +} // namespace unity -- cgit v1.2.3 From 0e5acaedb9cb419b7fc607de175fce23025805c2 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 10 Jun 2014 09:01:39 -0500 Subject: in alarm-queue-simple, call requeue() if time skew is detected. --- src/alarm-queue-simple.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/alarm-queue-simple.cpp') diff --git a/src/alarm-queue-simple.cpp b/src/alarm-queue-simple.cpp index 1c871bf..00608c9 100644 --- a/src/alarm-queue-simple.cpp +++ b/src/alarm-queue-simple.cpp @@ -35,7 +35,7 @@ SimpleAlarmQueue::SimpleAlarmQueue(const std::shared_ptr& clock, m_clock(clock), m_planner(planner), m_timer(timer), - m_time(clock->localtime()) + m_datetime(clock->localtime()) { m_planner->appointments().changed().connect([this](const std::vector&){ g_debug("AlarmQueue %p calling requeue() due to appointments changed", this); @@ -45,8 +45,8 @@ SimpleAlarmQueue::SimpleAlarmQueue(const std::shared_ptr& clock, m_clock->minute_changed.connect([=]{ const auto now = m_clock->localtime(); constexpr auto skew_threshold_usec = int64_t{90} * G_USEC_PER_SEC; - const bool clock_jumped = std::abs(now - m_time) > skew_threshold_usec; - m_time = now; + const bool clock_jumped = std::abs(now - m_datetime) > skew_threshold_usec; + m_datetime = now; if (clock_jumped) { g_debug("AlarmQueue %p calling requeue() due to clock skew", this); requeue(); -- cgit v1.2.3 From 03a7615f1ff6f4bb1d8bf955c042151336edac9b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 10 Jun 2014 11:56:32 -0500 Subject: in SimpleAlarmQueue, the 'alarms we don't want to trigger' list needs to be composed of uid + timestamp. Keying off of only timestamp doesn't work because UIDs can be recycled as users edit and reuse alarms. --- src/alarm-queue-simple.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'src/alarm-queue-simple.cpp') diff --git a/src/alarm-queue-simple.cpp b/src/alarm-queue-simple.cpp index 00608c9..2e36380 100644 --- a/src/alarm-queue-simple.cpp +++ b/src/alarm-queue-simple.cpp @@ -79,7 +79,8 @@ void SimpleAlarmQueue::requeue() // kick any current alarms for (auto current : find_current_alarms()) { - m_triggered.insert(current.uid); + const std::pair trig {current.uid, current.begin}; + m_triggered.insert(trig); m_alarm_reached(current); } @@ -103,16 +104,26 @@ bool SimpleAlarmQueue::find_next_alarm(Appointment& setme) const const auto now = m_clock->localtime(); const auto beginning_of_minute = now.add_full (0, 0, 0, 0, 0, -now.seconds()); - for(const auto& walk : m_planner->appointments().get()) + const auto appointments = m_planner->appointments().get(); + g_message ("planner has %zu appointments in it", (size_t)appointments.size()); + + for(const auto& walk : appointments) { - if (m_triggered.count(walk.uid)) // did we already use this one? + const std::pair trig {walk.uid, walk.begin}; + if (m_triggered.count(trig)) { + g_message ("skipping; already used"); continue; + } - if (walk.begin < beginning_of_minute) // has this one already passed? + if (walk.begin < beginning_of_minute) { // has this one already passed? + g_message ("skipping; too old"); continue; + } - if (found && (tmp.begin < walk.begin)) // do we already have a better match? + if (found && (tmp.begin < walk.begin)) { // do we already have a better match? + g_message ("skipping; bad match"); continue; + } tmp = walk; found = true; @@ -133,7 +144,8 @@ std::vector SimpleAlarmQueue::find_current_alarms() const for(const auto& walk : m_planner->appointments().get()) { - if (m_triggered.count(walk.uid)) // did we already use this one? + const std::pair trig {walk.uid, walk.begin}; + if (m_triggered.count(trig)) // did we already use this one? continue; if (!DateTime::is_same_minute(now, walk.begin)) continue; -- cgit v1.2.3 From a5e5f4ccf55c61be72daa28e4e5b581a6dd9571b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 10 Jun 2014 12:01:57 -0500 Subject: remove some debug tracers that shouldn't've been committed --- src/alarm-queue-simple.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'src/alarm-queue-simple.cpp') diff --git a/src/alarm-queue-simple.cpp b/src/alarm-queue-simple.cpp index 2e36380..fa6c0bc 100644 --- a/src/alarm-queue-simple.cpp +++ b/src/alarm-queue-simple.cpp @@ -105,25 +105,19 @@ bool SimpleAlarmQueue::find_next_alarm(Appointment& setme) const const auto beginning_of_minute = now.add_full (0, 0, 0, 0, 0, -now.seconds()); const auto appointments = m_planner->appointments().get(); - g_message ("planner has %zu appointments in it", (size_t)appointments.size()); + g_debug ("planner has %zu appointments in it", (size_t)appointments.size()); for(const auto& walk : appointments) { const std::pair trig {walk.uid, walk.begin}; - if (m_triggered.count(trig)) { - g_message ("skipping; already used"); + if (m_triggered.count(trig)) continue; - } - if (walk.begin < beginning_of_minute) { // has this one already passed? - g_message ("skipping; too old"); + if (walk.begin < beginning_of_minute) // has this one already passed? continue; - } - if (found && (tmp.begin < walk.begin)) { // do we already have a better match? - g_message ("skipping; bad match"); + if (found && (tmp.begin < walk.begin)) // do we already have a better match? continue; - } tmp = walk; found = true; -- cgit v1.2.3