Host C Specs


Directory: src/c/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 17 / 0 / 17
Functions: 100.0% 3 / 0 / 3
Branches: 100.0% 12 / 0 / 12

pebble/io/stores/store_poll.h
Line Branch Exec Source
1 /**
2 * @file store_poll.h
3 * @brief Wall-clock deadlines for the stores that poll the phone.
4 *
5 * @ingroup lib_stores
6 */
7 #pragma once
8 #include <pebble.h>
9 #include <time.h>
10
11 /**
12 * @addtogroup lib_stores
13 * @{
14 */
15
16 /**
17 * @brief The next wall-clock second a poll of this interval falls due.
18 *
19 * Counted from the epoch rather than from launch, so two watches started minutes apart poll at
20 * the same moments and a relaunch does not shift the phase.
21 *
22 * @param poll_min Minutes between polls. Must be above 0.
23 * @param now The current wall-clock time.
24 * @return The second the next poll is due.
25 */
26 15 static inline time_t store_poll_next(int poll_min, time_t now)
27 {
28 15 time_t interval = (time_t)poll_min * SECONDS_PER_MINUTE;
29 15 return ((now / interval) + 1) * interval;
30 }
31
32 /**
33 * @brief Whether @p next has come round, moving it on to the following deadline when it has.
34 *
35 * A clock that jumps forward just fires once and carries on. One that jumps back would strand the
36 * deadline more than an interval ahead, so that case is pulled back in.
37 *
38 * @param poll_min Minutes between polls. 0 or less means polling is off and this is never due.
39 * @param[in,out] next The store's deadline, read and updated in place.
40 * @param now The current wall-clock time.
41 * @return Whether a poll should go out now.
42 */
43 13 static inline bool store_poll_due(int poll_min, time_t *next, time_t now)
44 {
45
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
13 if (poll_min <= 0)
46 {
47 2 return false;
48 }
49
50 11 time_t interval = (time_t)poll_min * SECONDS_PER_MINUTE;
51
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 10 times.
11 if (*next > now + interval)
52 {
53 1 *next = store_poll_next(poll_min, now);
54 }
55
56
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6 times.
11 if (now < *next)
57 {
58 5 return false;
59 }
60
61 6 *next = store_poll_next(poll_min, now);
62 6 return true;
63 }
64
65 /**
66 * @brief Whether a reading is worth asking for again now that the phone is back.
67 *
68 * The phone's side may have been closed the whole time it was away, so a face catches up a reading
69 * that went stale meanwhile. Only a reading that never arrived, or one at least its own interval old,
70 * is asked for, so bluetooth dropping in and out cannot fetch faster than the normal polling. Polling
71 * turned off is left alone, the same as its store.
72 *
73 * @param age_s Seconds since the reading arrived, or below 0 when it never has.
74 * @param poll_min Minutes between polls. 0 or less means polling is off.
75 * @return Whether to ask for the reading again.
76 */
77 4 static inline bool store_poll_reconnect_due(int age_s, int poll_min)
78 {
79
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 3 times.
4 if (poll_min <= 0)
80 {
81 1 return false;
82 }
83 // a clock set back makes a saved reading's age negative too, so it reads as never arrived and the
84 // reconnect asks again. the first answer resets the age, and a reconnect means the phone is there
85 // to give one, so it costs about one fetch. counting that age as fresh instead would skip every
86 // reconnect fetch until the clock caught up, which can be hours
87
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
3 return age_s < 0 || age_s >= poll_min * SECONDS_PER_MINUTE;
88 }
89
90 /** @brief One store's polling: its interval, whether it polls at all, and when it is next due. */
91 typedef struct
92 {
93 time_t next; ///< Wall-clock second the next recurring poll is due
94 int poll_min; ///< Minutes between polls. 0 or less means no recurring poll
95 bool live; ///< True on a live face. A store seeded with fixtures never polls
96 } StorePoll;
97
98 /**
99 * @brief Take a store's interval and whether it is live, as its init and its reconfigure both do.
100 *
101 * Both are always recorded. The deadline only moves when polling is on, and then to the next
102 * interval boundary, so a save can bring a poll nearer but never make one come faster than the
103 * interval allows.
104 *
105 * @param[in,out] poll The store's polling state.
106 * @param poll_min Minutes between polls. 0 or less turns polling off.
107 * @param live Whether the store is live.
108 * @param now The current wall-clock time.
109 * @return Whether polling is on, which is when a store may arm its first or catch-up fetch.
110 */
111 bool store_poll_set(StorePoll *poll, int poll_min, bool live, time_t now);
112
113 /**
114 * @brief A store's turn on the face's cadence: whether a poll should go out now.
115 *
116 * @param[in,out] poll The store's polling state. The deadline moves on when a poll is due.
117 * @param now The current wall-clock time.
118 * @return Whether to ask the phone now.
119 */
120 bool store_poll_turn(StorePoll *poll, time_t now);
121
122 /** @} */
123