Adding a FOREACH_CONTINUE() variant to queue(3)
Lawrence Stewart
lstewart at freebsd.org
Wed May 1 04:40:56 UTC 2013
Hi Alfred,
On 05/01/13 14:10, Alfred Perlstein wrote:
> On 4/30/13 8:57 PM, Lawrence Stewart wrote:
>> [reposting from freebsd-arch@ - was probably the wrong list]
>>
>> Hi all,
>>
>> I've had use for these a few times now when wanting to restart a loop at
>> a previously found element, and wonder if there are any thoughts about
>> sticking them (and equivalents for other list types) in <sys/queue.h>?
>>
>> Cheers,
>> Lawrence
>>
>> #define TAILQ_FOREACH_CONTINUE(var, head, field) \
>> for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
>> (var); \
>> (var) = TAILQ_NEXT((var), field))
>>
>>
>> #define SLIST_FOREACH_CONTINUE(var, head, field) \
>> for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
>> (var); \
>> (var) = SLIST_NEXT((var), field))
>
> Can you show a few uses please? If it can significantly cut down on
> extra code it seems wise.
Sure.
Here is an excerpt from the MPTCP patch at [1] related to TCP reassembly
(more uses are in the patch if you search for FOREACH_CONTINUE):
+ /*
+ * Search from segment just inserted towards end of list looking
+ * for a hole.
+ */
+ q = te;
+ TAILQ_FOREACH_CONTINUE(q, tp->t_segq, tqe_q) {
+ nq = TAILQ_NEXT(q, tqe_q);
+ if (nq != NULL &&
+ q->tqe_th->th_seq + q->tqe_len != nq->tqe_th->th_seq) {
+ /* Found the first out of sequence segment in the reass list. */
+ tp->t_segq->disordered = nq;
+ break;
+ }
+ }
+ if (q == NULL)
+ tp->t_segq->disordered = NULL;
Here is an excerpt from some unreleased code I'm working on that writes
a full sysctl MIB path (e.g. "a.b.c.d") into a string buffer "name",
progressing through the sysctl tree one MIB path at a time each time the
function is called (oid is initialised to be the point in the sysctl
tree from the last time the function was called):
+ again:
+ /* Depth first traversal of tree. */
+ SLIST_FOREACH_CONTINUE(oid, lsp, oid_link) {
+ if (layer == 0 && strcmp(oid->oid_name, "sysctl") == 0)
+ continue;
+
+ namelen = strlcat(name, oid->oid_name, remain);
+ remain -= namelen;
+ layer_state[layer].layer = lsp;
+ layer_state[layer].branch = oid;
+
+ if (((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) &&
+ !SLIST_EMPTY(SYSCTL_CHILDREN(oid))) {
+ layer++;
+ lsp = SYSCTL_CHILDREN(oid);
+ oid = NULL;
+ *(name + namelen) = '.';
+ namelen++;
+ *(name + namelen) = '\0';
+ remain -= 1;
+ goto again;
+ } else {
+ /* Leaf node. */
+ return (namelen);
+ }
+ }
Cheers,
Lawrence
[1]
http://caia.swin.edu.au/urp/newtcp/mptcp/tools/mptcp_v0.3_10.x.248226.patch
More information about the freebsd-hackers
mailing list