From e2a926de2f7b1d5ed8b83b801620b4ef5ad6993d Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 9 Jul 2017 10:11:59 +0800 Subject: [PATCH] linkedlist helpers --- lib/libwebsockets.h | 68 +++++++++++++++++++++++++++++++++++++ plugins/protocol_lws_mirror.c | 79 ++++++++++++++++++++----------------------- 2 files changed, 104 insertions(+), 43 deletions(-) diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 3358910..2e79395 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -4197,6 +4197,74 @@ lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr, ///@{ /** + * lws_start_foreach_ll(): linkedlist iterator helper start + * + * \param type: type of iteration, eg, struct xyz * + * \param it: iterator var name to create + * \param start: start of list + * + * This helper creates an iterator and starts a while (it) { + * loop. The iterator runs through the linked list starting at start and + * ends when it gets a NULL. + * The while loop should be terminated using lws_start_foreach_ll(). + */ +#define lws_start_foreach_ll(type, it, start)\ +{ \ + type it = start; \ + while (it) { + +/** + * lws_end_foreach_ll(): linkedlist iterator helper end + * + * \param it: same iterator var name given when starting + * \param nxt: member name in the iterator pointing to next list element + * + * This helper is the partner for lws_start_foreach_ll() that ends the + * while loop. + */ + +#define lws_end_foreach_ll(it, nxt) \ + it = it->nxt; \ + } \ +} + +/** + * lws_start_foreach_llp(): linkedlist pointer iterator helper start + * + * \param type: type of iteration, eg, struct xyz ** + * \param it: iterator var name to create + * \param start: start of list + * + * This helper creates an iterator and starts a while (it) { + * loop. The iterator runs through the linked list starting at the + * address of start and ends when it gets a NULL. + * The while loop should be terminated using lws_start_foreach_llp(). + * + * This helper variant iterates using a pointer to the previous linked-list + * element. That allows you to easily delete list members by rewriting the + * previous pointer to the element's next pointer. + */ +#define lws_start_foreach_llp(type, it, start)\ +{ \ + type it = &(start); \ + while (*(it)) { + +/** + * lws_end_foreach_llp(): linkedlist pointer iterator helper end + * + * \param it: same iterator var name given when starting + * \param nxt: member name in the iterator pointing to next list element + * + * This helper is the partner for lws_start_foreach_llp() that ends the + * while loop. + */ + +#define lws_end_foreach_llp(it, nxt) \ + it = &(*(it))->nxt; \ + } \ +} + +/** * lws_snprintf(): snprintf that truncates the returned length too * * \param str: destination buffer diff --git a/plugins/protocol_lws_mirror.c b/plugins/protocol_lws_mirror.c index 33af7ce..afac1b6 100644 --- a/plugins/protocol_lws_mirror.c +++ b/plugins/protocol_lws_mirror.c @@ -68,13 +68,12 @@ callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { struct per_session_data__lws_mirror *pss = - (struct per_session_data__lws_mirror *)user, **ppss, - *pss1; + (struct per_session_data__lws_mirror *)user; struct per_vhost_data__lws_mirror *v = (struct per_vhost_data__lws_mirror *) lws_protocol_vh_priv_get(lws_get_vhost(wsi), lws_get_protocol(wsi)); - struct lws_mirror_instance *mi, **pmi; + struct lws_mirror_instance *mi = NULL; char name[30]; int n, m, count_mi = 0; @@ -95,17 +94,16 @@ callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason, /* is there already a mirror instance of this name? */ - mi = v->mi_list; - while (mi) { - if (!strcmp(name, mi->name)) { - lwsl_notice("Joining existing mi %p '%s'\n", - mi, name); - /* yes... we will join it */ - break; - } + lws_start_foreach_ll(struct lws_mirror_instance *, + mi1, v->mi_list) { count_mi++; - mi = mi->next; - } + if (strcmp(name, mi1->name)) + continue; + /* yes... we will join it */ + lwsl_notice("Joining existing mi %p '%s'\n", mi1, name); + mi = mi1; + break; + } lws_end_foreach_ll(mi1, next); if (!mi) { @@ -123,7 +121,6 @@ callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason, strcpy(mi->name, name); mi->ringbuffer_head = 0; - lwsl_notice("Created new mi %p '%s'\n", mi, name); } @@ -147,42 +144,40 @@ callback_lws_mirror(struct lws *wsi, enum lws_callback_reasons reason, mi = pss->mi; if (!mi) break; - ppss = &mi->same_mi_pss_list; - while (*ppss) { + lws_start_foreach_llp(struct per_session_data__lws_mirror **, + ppss, mi->same_mi_pss_list) { if (*ppss == pss) { + *ppss = pss->same_mi_pss_list; break; } + } lws_end_foreach_llp(ppss, same_mi_pss_list); - ppss = &(*ppss)->same_mi_pss_list; - } + pss->mi = NULL; - if (!mi->same_mi_pss_list) { + if (mi->same_mi_pss_list) + break; - /* last pss unbound from mi... delete mi */ + /* last pss unbound from mi... delete mi */ - pmi = &v->mi_list; - while (*pmi) { - if (*pmi == mi) { - *pmi = (*pmi)->next; + lws_start_foreach_llp(struct lws_mirror_instance **, + pmi, v->mi_list) { + if (*pmi != mi) + continue; - if (!pss->mi) - break; - lwsl_info("%s: mirror protocol cleaning up %p\n", __func__, v); - for (n = 0; n < ARRAY_SIZE(pss->mi->ringbuffer); n++) - if (pss->mi->ringbuffer[n].payload) { - free(pss->mi->ringbuffer[n].payload); - pss->mi->ringbuffer[n].payload = NULL; - } + *pmi = (*pmi)->next; - free(mi); - break; + lwsl_info("%s: mirror cleaniup %p\n", __func__, v); + for (n = 0; n < ARRAY_SIZE(mi->ringbuffer); n++) + if (mi->ringbuffer[n].payload) { + free(mi->ringbuffer[n].payload); + mi->ringbuffer[n].payload = NULL; } - count_mi++; - pmi = &(*pmi)->next; - } - } + + free(mi); + break; + } lws_end_foreach_llp(pmi, next); break; @@ -257,12 +252,10 @@ done: * ask for WRITABLE callback for every wsi bound to this * mirror instance */ - - pss1 = pss->mi->same_mi_pss_list; - while (pss1) { + lws_start_foreach_ll(struct per_session_data__lws_mirror *, + pss1, pss->mi->same_mi_pss_list) { lws_callback_on_writable(pss1->wsi); - pss1 = pss1->same_mi_pss_list; - } + } lws_end_foreach_ll(pss1, same_mi_pss_list); break; default: -- 2.7.4