From 8c7daeeb87abd0be1b96169da18baf018c4859c9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 3 Apr 2015 13:11:39 -0500 Subject: add the new Alarm class as an argument to the alarm queue class --- src/alarm-queue-simple.cpp | 226 ++++++++++++++++++++++++++------------------- 1 file changed, 133 insertions(+), 93 deletions(-) (limited to 'src/alarm-queue-simple.cpp') diff --git a/src/alarm-queue-simple.cpp b/src/alarm-queue-simple.cpp index f45e61a..db0fd21 100644 --- a/src/alarm-queue-simple.cpp +++ b/src/alarm-queue-simple.cpp @@ -20,134 +20,174 @@ #include #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_datetime(clock->localtime()) +class SimpleAlarmQueue::Impl { - 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_datetime) > skew_threshold_usec; - m_datetime = now; - if (clock_jumped) { - g_debug("AlarmQueue %p calling requeue() due to clock skew", this); +public: + + Impl(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_datetime{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_datetime) > skew_threshold_usec; + m_datetime = now; + if (clock_jumped) { + g_debug("AlarmQueue %p calling requeue() due to clock skew", this); + requeue(); + } + }); + + m_timer->timeout().connect([this](){ + g_debug("AlarmQueue %p calling requeue() due to timeout", this); + requeue(); + }); - m_timer->timeout().connect([this](){ - g_debug("AlarmQueue %p calling requeue() due to timeout", this); requeue(); - }); - - requeue(); -} + } -SimpleAlarmQueue::~SimpleAlarmQueue() -{ -} + ~Impl() + { + } -core::Signal& SimpleAlarmQueue::alarm_reached() -{ - return m_alarm_reached; -} + core::Signal& alarm_reached() + { + return m_alarm_reached; + } -/*** -**** -***/ +private: -void SimpleAlarmQueue::requeue() -{ - // kick any current alarms - for (auto current : find_current_alarms()) + void requeue() { - const std::pair trig {current.uid, current.begin}; - m_triggered.insert(trig); - m_alarm_reached(current); + // kick any current alarms + for (const auto& appointment : m_planner->appointments().get()) + { + Alarm alarm; + if (appointment_get_current_alarm(appointment, alarm)) + { + m_triggered.insert(std::make_pair(appointment.uid, alarm.time)); + m_alarm_reached(appointment, alarm); + } + } + + // idle until the next alarm + Alarm next; + if (find_next_alarm(next)) + { + g_debug ("setting timer to wake up for next appointment '%s' at %s", + next.text.c_str(), + next.time.format("%F %T").c_str()); + + m_timer->set_wakeup_time(next.time); + } } - // idle until the next alarm - Appointment next; - if (find_next_alarm(next)) + // find the next alarm that will kick now or in the future + bool find_next_alarm(Alarm& setme) const { - g_debug ("setting timer to wake up for next appointment '%s' at %s", - next.summary.c_str(), - next.begin.format("%F %T").c_str()); + bool found = false; + Alarm best; + const auto now = m_clock->localtime(); + const auto beginning_of_minute = now.start_of_minute(); - m_timer->set_wakeup_time(next.begin); - } -} + const auto appointments = m_planner->appointments().get(); + g_debug ("planner has %zu appointments in it", (size_t)appointments.size()); -// 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.start_of_minute(); + for(const auto& appointment : appointments) + { + for(const auto& alarm : appointment.alarms) + { + const std::pair trig{appointment.uid, alarm.time}; + if (m_triggered.count(trig)) + continue; - const auto appointments = m_planner->appointments().get(); - g_debug ("planner has %zu appointments in it", (size_t)appointments.size()); + if (alarm.time < beginning_of_minute) // has this one already passed? + continue; - for(const auto& walk : appointments) - { - const std::pair trig {walk.uid, walk.begin}; - if (m_triggered.count(trig)) - continue; + if (found && (best.time < alarm.time)) // do we already have a better match? + continue; - if (walk.begin < beginning_of_minute) // has this one already passed? - continue; + best = alarm; + found = true; + } + } - if (found && (tmp.begin < walk.begin)) // do we already have a better match? - continue; + if (found) + setme = best; - tmp = walk; - found = true; + return found; } - if (found) - setme = tmp; - return found; -} + bool appointment_get_current_alarm(const Appointment& appointment, Alarm& setme) const + { + const auto now = m_clock->localtime(); -// find the alarm(s) that should kick right now -std::vector SimpleAlarmQueue::find_current_alarms() const -{ - std::vector appointments; + for (const auto& alarm : appointment.alarms) + { + const auto trig = std::make_pair(appointment.uid, alarm.time); + if (m_triggered.count(trig)) // did we already use this one? + continue; + + if (DateTime::is_same_minute(now, alarm.time)) + { + setme = alarm; + return true; + } + } - const auto now = m_clock->localtime(); + return false; + } - for(const auto& walk : m_planner->appointments().get()) - { - 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; - appointments.push_back(walk); - } + std::set> m_triggered; + const std::shared_ptr m_clock; + const std::shared_ptr m_planner; + const std::shared_ptr m_timer; + core::Signal m_alarm_reached; + DateTime m_datetime; +}; + +/*** +**** Public API +***/ + - return appointments; +SimpleAlarmQueue::SimpleAlarmQueue(const std::shared_ptr& clock, + const std::shared_ptr& planner, + const std::shared_ptr& timer): + impl{new Impl{clock, planner, timer}} +{ +} + +SimpleAlarmQueue::~SimpleAlarmQueue() +{ +} + +core::Signal& +SimpleAlarmQueue::alarm_reached() +{ + return impl->alarm_reached(); } /*** -- cgit v1.2.3 From 242bab5395d808b0c25b2df8971c11a5f8932001 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 5 Apr 2015 18:27:08 -0500 Subject: in SimpleAlarmQueue, use references instead of copies when copies aren't necessary --- 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 db0fd21..ae7722c 100644 --- a/src/alarm-queue-simple.cpp +++ b/src/alarm-queue-simple.cpp @@ -110,14 +110,14 @@ private: const auto now = m_clock->localtime(); const auto beginning_of_minute = now.start_of_minute(); - const auto appointments = m_planner->appointments().get(); + const auto& appointments = m_planner->appointments().get(); g_debug ("planner has %zu appointments in it", (size_t)appointments.size()); for(const auto& appointment : appointments) { for(const auto& alarm : appointment.alarms) { - const std::pair trig{appointment.uid, alarm.time}; + const std::pair trig{appointment.uid, alarm.time}; if (m_triggered.count(trig)) continue; @@ -145,7 +145,7 @@ private: for (const auto& alarm : appointment.alarms) { - const auto trig = std::make_pair(appointment.uid, alarm.time); + const std::pair trig{appointment.uid, alarm.time}; if (m_triggered.count(trig)) // did we already use this one? continue; -- cgit v1.2.3 From 006858f8955ebeda75ce6cca152bbf42af7da3da Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 6 Apr 2015 13:29:07 -0500 Subject: in SimpleAlarmQueue, reduce a lambda capture to only the fields it needs --- src/alarm-queue-simple.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/alarm-queue-simple.cpp') diff --git a/src/alarm-queue-simple.cpp b/src/alarm-queue-simple.cpp index ae7722c..d04c0fc 100644 --- a/src/alarm-queue-simple.cpp +++ b/src/alarm-queue-simple.cpp @@ -47,7 +47,7 @@ public: requeue(); }); - m_clock->minute_changed.connect([=]{ + m_clock->minute_changed.connect([this]{ 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_datetime) > skew_threshold_usec; -- cgit v1.2.3 From 81f4d9916f4915365e7e271354771b71e0ef2c38 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 6 Apr 2015 14:17:26 -0500 Subject: in SimpleAlarmQueue, make the signature for find_next_alarm() and appointment_get_current_alarm() suck less. --- src/alarm-queue-simple.cpp | 50 +++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 29 deletions(-) (limited to 'src/alarm-queue-simple.cpp') diff --git a/src/alarm-queue-simple.cpp b/src/alarm-queue-simple.cpp index d04c0fc..19e5208 100644 --- a/src/alarm-queue-simple.cpp +++ b/src/alarm-queue-simple.cpp @@ -79,38 +79,37 @@ private: void requeue() { + const auto appointments = m_planner->appointments().get(); + const Alarm* alarm; + // kick any current alarms - for (const auto& appointment : m_planner->appointments().get()) + for (const auto& appointment : appointments) { - Alarm alarm; - if (appointment_get_current_alarm(appointment, alarm)) + if ((alarm = appointment_get_current_alarm(appointment))) { - m_triggered.insert(std::make_pair(appointment.uid, alarm.time)); - m_alarm_reached(appointment, alarm); + m_triggered.insert(std::make_pair(appointment.uid, alarm->time)); + m_alarm_reached(appointment, *alarm); } } // idle until the next alarm - Alarm next; - if (find_next_alarm(next)) + if ((alarm = find_next_alarm(appointments))) { g_debug ("setting timer to wake up for next appointment '%s' at %s", - next.text.c_str(), - next.time.format("%F %T").c_str()); + alarm->text.c_str(), + alarm->time.format("%F %T").c_str()); - m_timer->set_wakeup_time(next.time); + m_timer->set_wakeup_time(alarm->time); } } - // find the next alarm that will kick now or in the future - bool find_next_alarm(Alarm& setme) const + // return the next Alarm (if any) that will kick now or in the future + const Alarm* find_next_alarm(const std::vector& appointments) const { - bool found = false; - Alarm best; + const Alarm* best {}; const auto now = m_clock->localtime(); const auto beginning_of_minute = now.start_of_minute(); - const auto& appointments = m_planner->appointments().get(); g_debug ("planner has %zu appointments in it", (size_t)appointments.size()); for(const auto& appointment : appointments) @@ -124,22 +123,18 @@ private: if (alarm.time < beginning_of_minute) // has this one already passed? continue; - if (found && (best.time < alarm.time)) // do we already have a better match? + if (best && (best->time < alarm.time)) // do we already have a better match? continue; - best = alarm; - found = true; + best = &alarm; } } - if (found) - setme = best; - - return found; + return best; } - - bool appointment_get_current_alarm(const Appointment& appointment, Alarm& setme) const + // return the Appointment's current Alarm (if any) + const Alarm* appointment_get_current_alarm(const Appointment& appointment) const { const auto now = m_clock->localtime(); @@ -150,13 +145,10 @@ private: continue; if (DateTime::is_same_minute(now, alarm.time)) - { - setme = alarm; - return true; - } + return &alarm; } - return false; + return nullptr; } -- cgit v1.2.3 From 392788b1db2d60cd73cac12e58fbc4e6ce304d9e Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 6 Apr 2015 14:26:24 -0500 Subject: in SimpleAlarmQueue, add a new method 'bool already_triggered() const' to reduce code overlapl between find_next_alarm() and appointment_get_current_alarm() --- src/alarm-queue-simple.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'src/alarm-queue-simple.cpp') diff --git a/src/alarm-queue-simple.cpp b/src/alarm-queue-simple.cpp index 19e5208..921e8d2 100644 --- a/src/alarm-queue-simple.cpp +++ b/src/alarm-queue-simple.cpp @@ -103,6 +103,12 @@ private: } } + bool already_triggered (const Appointment& appt, const Alarm& alarm) const + { + const std::pair key{appt.uid, alarm.time}; + return m_triggered.count(key) != 0; + } + // return the next Alarm (if any) that will kick now or in the future const Alarm* find_next_alarm(const std::vector& appointments) const { @@ -116,8 +122,7 @@ private: { for(const auto& alarm : appointment.alarms) { - const std::pair trig{appointment.uid, alarm.time}; - if (m_triggered.count(trig)) + if (already_triggered(appointment, alarm)) continue; if (alarm.time < beginning_of_minute) // has this one already passed? @@ -139,14 +144,8 @@ private: const auto now = m_clock->localtime(); for (const auto& alarm : appointment.alarms) - { - const std::pair trig{appointment.uid, alarm.time}; - if (m_triggered.count(trig)) // did we already use this one? - continue; - - if (DateTime::is_same_minute(now, alarm.time)) + if (!already_triggered(appointment, alarm) && DateTime::is_same_minute(now, alarm.time)) return &alarm; - } return nullptr; } -- cgit v1.2.3