From 181231f3ff9dce1d6edb3d264422bbc2a1bfe406 Mon Sep 17 00:00:00 2001 From: Devaev Maxim Date: Sun, 28 Mar 2021 21:51:34 +0300 Subject: [PATCH] common list operations --- src/libs/tools.h | 34 ++++++++++++++++++++++++++++++++-- src/ustreamer/http/server.c | 33 ++++++++------------------------- 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/libs/tools.h b/src/libs/tools.h index c2b4416..157b0d5 100644 --- a/src/libs/tools.h +++ b/src/libs/tools.h @@ -35,6 +35,9 @@ #include +#define INLINE inline __attribute__((always_inline)) +#define UNUSED __attribute__((unused)) + #define A_CALLOC(_dest, _nmemb) assert((_dest = calloc(_nmemb, sizeof(*(_dest))))) #define A_REALLOC(_dest, _nmemb) assert((_dest = realloc(_dest, _nmemb * sizeof(*(_dest))))) #define MEMSET_ZERO(_obj) memset(&(_obj), 0, sizeof(_obj)) @@ -43,8 +46,35 @@ #define ARRAY_LEN(_array) (sizeof(_array) / sizeof(_array[0])) -#define INLINE inline __attribute__((always_inline)) -#define UNUSED __attribute__((unused)) +#define LIST_ITERATE(_first, _item, ...) { \ + for (__typeof__(_first) _item = _first; _item;) { \ + __typeof__(_first) _next = _item->next; \ + __VA_ARGS__ \ + _item = _next; \ + } \ + } + +#define LIST_APPEND(_first, _item) { \ + if (_first == NULL) { \ + _first = _item; \ + } else { \ + __typeof__(_first) _last = _first; \ + for (; _last->next; _last = _last->next); \ + _item->prev = _last; \ + _last->next = _item; \ + } \ + } + +#define LIST_REMOVE(_first, _item) { \ + if (_item->prev == NULL) { \ + _first = _item->next; \ + } else { \ + _item->prev->next = _item->next; \ + } \ + if (_item->next != NULL) { \ + _item->next->prev = _item->prev; \ + } \ + } INLINE const char *bool_to_string(bool flag) { diff --git a/src/ustreamer/http/server.c b/src/ustreamer/http/server.c index 163b60f..4a594b9 100644 --- a/src/ustreamer/http/server.c +++ b/src/ustreamer/http/server.c @@ -93,13 +93,11 @@ void server_destroy(server_s *server) { libevent_global_shutdown(); # endif - for (stream_client_s *client = RUN(stream_clients); client != NULL;) { - stream_client_s *next = client->next; + LIST_ITERATE(RUN(stream_clients), client, { free(client->key); free(client->hostport); free(client); - client = next; - } + }); if (RUN(auth_token)) { free(RUN(auth_token)); @@ -367,7 +365,7 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server) RUN(stream_clients_count) )); - for (stream_client_s * client = RUN(stream_clients); client != NULL; client = client->next) { + LIST_ITERATE(RUN(stream_clients), client, { assert(evbuffer_add_printf(buf, "\"%" PRIx64 "\": {\"fps\": %u, \"extra_headers\": %s, \"advance_headers\": %s," " \"dual_final_frames\": %s, \"zero_data\": %s}%s", @@ -379,7 +377,7 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server) bool_to_string(client->zero_data), (client->next ? ", " : "") )); - } + }); assert(evbuffer_add_printf(buf, "}}}}")); @@ -477,15 +475,7 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server client->hostport = _http_get_client_hostport(request); client->id = get_now_id(); - if (RUN(stream_clients) == NULL) { - RUN(stream_clients) = client; - } else { - stream_client_s *last = RUN(stream_clients); - - for (; last->next != NULL; last = last->next); - client->prev = last; - last->next = client; - } + LIST_APPEND(RUN(stream_clients), client); RUN(stream_clients_count) += 1; if (RUN(stream_clients_count) == 1) { @@ -673,14 +663,7 @@ static void _http_callback_stream_error(UNUSED struct bufferevent *buf_event, UN evhttp_connection_free(conn); } - if (client->prev == NULL) { - RUN(stream_clients) = client->next; - } else { - client->prev->next = client->next; - } - if (client->next != NULL) { - client->next->prev = client->prev; - } + LIST_REMOVE(RUN(stream_clients), client); free(client->key); free(client->hostport); free(client); @@ -692,7 +675,7 @@ static void _http_queue_send_stream(server_s *server, bool stream_updated, bool bool has_clients = false; bool queued = false; - for (stream_client_s *client = RUN(stream_clients); client != NULL; client = client->next) { + LIST_ITERATE(RUN(stream_clients), client, { struct evhttp_connection *conn = evhttp_request_get_connection(client->request); if (conn) { // Фикс для бага WebKit. При включенной опции дропа одинаковых фреймов, @@ -723,7 +706,7 @@ static void _http_queue_send_stream(server_s *server, bool stream_updated, bool has_clients = true; } - } + }); if (queued) { static unsigned queued_fps_accum = 0;