common list operations

This commit is contained in:
Devaev Maxim
2021-03-28 21:51:34 +03:00
parent 58569f0315
commit 181231f3ff
2 changed files with 40 additions and 27 deletions

View File

@@ -35,6 +35,9 @@
#include <sys/file.h> #include <sys/file.h>
#define INLINE inline __attribute__((always_inline))
#define UNUSED __attribute__((unused))
#define A_CALLOC(_dest, _nmemb) assert((_dest = calloc(_nmemb, sizeof(*(_dest))))) #define A_CALLOC(_dest, _nmemb) assert((_dest = calloc(_nmemb, sizeof(*(_dest)))))
#define A_REALLOC(_dest, _nmemb) assert((_dest = realloc(_dest, _nmemb * sizeof(*(_dest))))) #define A_REALLOC(_dest, _nmemb) assert((_dest = realloc(_dest, _nmemb * sizeof(*(_dest)))))
#define MEMSET_ZERO(_obj) memset(&(_obj), 0, sizeof(_obj)) #define MEMSET_ZERO(_obj) memset(&(_obj), 0, sizeof(_obj))
@@ -43,8 +46,35 @@
#define ARRAY_LEN(_array) (sizeof(_array) / sizeof(_array[0])) #define ARRAY_LEN(_array) (sizeof(_array) / sizeof(_array[0]))
#define INLINE inline __attribute__((always_inline)) #define LIST_ITERATE(_first, _item, ...) { \
#define UNUSED __attribute__((unused)) 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) { INLINE const char *bool_to_string(bool flag) {

View File

@@ -93,13 +93,11 @@ void server_destroy(server_s *server) {
libevent_global_shutdown(); libevent_global_shutdown();
# endif # endif
for (stream_client_s *client = RUN(stream_clients); client != NULL;) { LIST_ITERATE(RUN(stream_clients), client, {
stream_client_s *next = client->next;
free(client->key); free(client->key);
free(client->hostport); free(client->hostport);
free(client); free(client);
client = next; });
}
if (RUN(auth_token)) { if (RUN(auth_token)) {
free(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) 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, assert(evbuffer_add_printf(buf,
"\"%" PRIx64 "\": {\"fps\": %u, \"extra_headers\": %s, \"advance_headers\": %s," "\"%" PRIx64 "\": {\"fps\": %u, \"extra_headers\": %s, \"advance_headers\": %s,"
" \"dual_final_frames\": %s, \"zero_data\": %s}%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), bool_to_string(client->zero_data),
(client->next ? ", " : "") (client->next ? ", " : "")
)); ));
} });
assert(evbuffer_add_printf(buf, "}}}}")); 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->hostport = _http_get_client_hostport(request);
client->id = get_now_id(); client->id = get_now_id();
if (RUN(stream_clients) == NULL) { LIST_APPEND(RUN(stream_clients), client);
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;
}
RUN(stream_clients_count) += 1; RUN(stream_clients_count) += 1;
if (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); evhttp_connection_free(conn);
} }
if (client->prev == NULL) { LIST_REMOVE(RUN(stream_clients), client);
RUN(stream_clients) = client->next;
} else {
client->prev->next = client->next;
}
if (client->next != NULL) {
client->next->prev = client->prev;
}
free(client->key); free(client->key);
free(client->hostport); free(client->hostport);
free(client); free(client);
@@ -692,7 +675,7 @@ static void _http_queue_send_stream(server_s *server, bool stream_updated, bool
bool has_clients = false; bool has_clients = false;
bool queued = 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); struct evhttp_connection *conn = evhttp_request_get_connection(client->request);
if (conn) { if (conn) {
// Фикс для бага WebKit. При включенной опции дропа одинаковых фреймов, // Фикс для бага WebKit. При включенной опции дропа одинаковых фреймов,
@@ -723,7 +706,7 @@ static void _http_queue_send_stream(server_s *server, bool stream_updated, bool
has_clients = true; has_clients = true;
} }
} });
if (queued) { if (queued) {
static unsigned queued_fps_accum = 0; static unsigned queued_fps_accum = 0;