Loading...
Searching...
No Matches
outbox_queue.h
Go to the documentation of this file.
1
15#pragma once
16#include <stdbool.h>
17
22
24#define OUTBOX_QUEUE_MAX 6
25
38
42typedef struct
43{
46} OutboxJob;
47
61
68static inline bool outbox_busy(const OutboxQueue *outbox)
69{
70 return outbox->inflight.kind != OUTBOX_NONE;
71}
72
83static inline bool outbox_pending(const OutboxQueue *outbox, OutboxKind kind)
84{
85 if (kind == OUTBOX_NONE)
86 {
87 // the empty flight slot and every unused array entry read as OUTBOX_NONE, so without this
88 // an idle outbox would answer that nothing is already pending
89 return false;
90 }
91
92 if (outbox->inflight.kind == kind)
93 {
94 return true;
95 }
96
97 for (int i = 0; i < outbox->queue_len; i++)
98 {
99 if (outbox->queue[i].kind == kind)
100 {
101 return true;
102 }
103 }
104
105 for (int i = 0; i < outbox->failed_len; i++)
106 {
107 if (outbox->failed[i].kind == kind)
108 {
109 return true;
110 }
111 }
112
113 return false;
114}
115
124static inline bool outbox_push(OutboxQueue *outbox, OutboxKind kind, int retries)
125{
126 if (outbox_pending(outbox, kind) || outbox->queue_len >= OUTBOX_QUEUE_MAX)
127 {
128 return false;
129 }
130
131 outbox->queue[outbox->queue_len].kind = kind;
132 outbox->queue[outbox->queue_len].retries_left = retries;
133 outbox->queue_len++;
134 return true;
135}
136
142static inline void outbox_pop_front(OutboxQueue *outbox)
143{
144 for (int i = 1; i < outbox->queue_len; i++)
145 {
146 outbox->queue[i - 1] = outbox->queue[i];
147 }
148
149 if (outbox->queue_len > 0)
150 {
151 outbox->queue_len--;
152 }
153}
154
163static inline void outbox_take_head(OutboxQueue *outbox)
164{
165 if (outbox->queue_len == 0)
166 {
167 return; // outbox_clear leaves the array behind, so an empty queue still has one to read
168 }
169
170 outbox->inflight = outbox->queue[0];
171 outbox_pop_front(outbox);
172}
173
181{
182 OutboxJob settled = outbox->inflight;
183 outbox->inflight.kind = OUTBOX_NONE;
184 return settled;
185}
186
193static inline void outbox_hold_failed(OutboxQueue *outbox, OutboxJob job)
194{
195 // a failure reported once the slot is already free comes with no job, and holding it would
196 // queue a send for nothing ahead of the real requests
197 if (job.kind == OUTBOX_NONE || job.retries_left <= 0)
198 {
199 return;
200 }
201
202 if (outbox->failed_len < OUTBOX_QUEUE_MAX)
203 {
204 outbox->failed[outbox->failed_len].kind = job.kind;
205 outbox->failed[outbox->failed_len].retries_left = job.retries_left - 1;
206 outbox->failed_len++;
207 }
208}
209
216static inline int outbox_retry_pass(OutboxQueue *outbox)
217{
218 int moved = 0;
219
220 while (outbox->failed_len > 0 && outbox->queue_len < OUTBOX_QUEUE_MAX)
221 {
222 outbox->queue[outbox->queue_len++] = outbox->failed[0];
223 for (int i = 1; i < outbox->failed_len; i++)
224 {
225 outbox->failed[i - 1] = outbox->failed[i];
226 }
227 outbox->failed_len--;
228 moved++;
229 }
230
231 return moved;
232}
233
242static inline void outbox_clear(OutboxQueue *outbox)
243{
244 outbox->queue_len = 0;
245 outbox->failed_len = 0;
246}
247
static void outbox_hold_failed(OutboxQueue *outbox, OutboxJob job)
Hold a nacked job for the next pass, if it still has retries.
Definition outbox_queue.h:193
static bool outbox_push(OutboxQueue *outbox, OutboxKind kind, int retries)
Add a job to the work queue unless its kind is already pending.
Definition outbox_queue.h:124
OutboxKind
What an outbox job sends.
Definition outbox_queue.h:30
static bool outbox_busy(const OutboxQueue *outbox)
Whether anything is in flight, which is what says the outbox is busy.
Definition outbox_queue.h:68
static int outbox_retry_pass(OutboxQueue *outbox)
Move the whole failed set back into the work queue for another pass.
Definition outbox_queue.h:216
static bool outbox_pending(const OutboxQueue *outbox, OutboxKind kind)
Whether this kind is already somewhere in the outbox.
Definition outbox_queue.h:83
static void outbox_clear(OutboxQueue *outbox)
Forget everything waiting, for a phone that is no longer there.
Definition outbox_queue.h:242
static void outbox_take_head(OutboxQueue *outbox)
Take the head of the queue as the job now in flight.
Definition outbox_queue.h:163
static void outbox_pop_front(OutboxQueue *outbox)
Drop the front job off the work queue, shifting the rest forward.
Definition outbox_queue.h:142
static OutboxJob outbox_release(OutboxQueue *outbox)
Mark whatever was in flight as settled, whichever way it went.
Definition outbox_queue.h:180
#define OUTBOX_QUEUE_MAX
Most jobs the work queue or the failed set holds at once.
Definition outbox_queue.h:24
@ OUTBOX_STOCK
A stock request.
Definition outbox_queue.h:35
@ OUTBOX_CALENDAR
A calendar request.
Definition outbox_queue.h:36
@ OUTBOX_FRESH
The short settings reply, only whether the watch booted with nothing saved.
Definition outbox_queue.h:34
@ OUTBOX_SETTINGS
The settings reply.
Definition outbox_queue.h:33
@ OUTBOX_NONE
The zero value, so a default-initialized job slot reads as nothing rather than a real request.
Definition outbox_queue.h:31
@ OUTBOX_WEATHER
A weather request.
Definition outbox_queue.h:32
One job waiting to go out, or already in flight.
Definition outbox_queue.h:43
OutboxKind kind
What this job sends.
Definition outbox_queue.h:44
int retries_left
Retry passes left after a failed send.
Definition outbox_queue.h:45
Everything the outbox is holding: what is waiting, what nacked, and what is out.
Definition outbox_queue.h:54
OutboxJob queue[OUTBOX_QUEUE_MAX]
This pass's work queue, oldest first.
Definition outbox_queue.h:55
OutboxJob inflight
The job in flight, OUTBOX_NONE when nothing is out.
Definition outbox_queue.h:59
int failed_len
How many jobs are in the failed set.
Definition outbox_queue.h:58
OutboxJob failed[OUTBOX_QUEUE_MAX]
Requests that nacked this pass, held for the next.
Definition outbox_queue.h:57
int queue_len
How many jobs are in the queue.
Definition outbox_queue.h:56