From 997ed5132d7e485d3844dc170598cf50989e3c91 Mon Sep 17 00:00:00 2001 From: nikto_b Date: Tue, 21 Jan 2025 19:47:52 +0300 Subject: [PATCH] Add readme --- README.md | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 59 +++++++++++++++++++-------------- 2 files changed, 131 insertions(+), 25 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..71a14be --- /dev/null +++ b/README.md @@ -0,0 +1,97 @@ +# ptQueue +Сищная либа для "потокобезопасных" очередей на односвязном списке для ситуаций когда есть только один писатель. +После передачи объекта в очередь, писатель теряет владение объектом и его управление переходит к читателю/читателям. + +Как использовать: +```C +#include // для abort, malloc, free + +#include "ptQueue.h" + +int main() +{ + char errbuf[1024]; + + + ptQueue* q = ptQueueCreate(errbuf); + if(q == NULL) + { + // Случай когда нет памяти на инициализацию + printf("Failed to create out q: %s\n", errbuf); + abort(); + } + + for(int i = 0; i < 4096; i++) + { + int* payload = malloc(sizeof(int)); + if(payload == NULL) + { + abort(); + } + *payload = i; + + int exitCode = ptQueuePush(q, payload, errbuf); + if(exitCode) + { + /* + * При каждом push выполняется аллокация элемента очереди, + * может вернуть NULL + */ + printf("Unable to push: %s\n", errbuf); + abort(); + } + } + + // Сами записали - сами и прочитаем с самого начала + ptQueueElem* tailIn = q->haed; + + while (1) + { + void* payload = atomic_load(&(tailIn->payload)); + if(payload == NULL) + { + /* + * Когда в очереди не осталось данных, + * в текущем хвосте *payload будет NULL, + * значит ждём новых данных + */ + microsecond_sleep(100); + continue; + } + int* code = payload; + + if(*code == 4095) + { + free(payload); + // Дошли до последнего отправленного элемента, выходим + break; + } + + /* + * Владение ушло от писателя, + * при этом после прочтения оно никому более не уйдёт, + * поэтому освобождаем память + */ + free(payload); + + ptQueueElem* newTail = atomic_load(&(tailIn->nextEl)); + if (newTail == NULL) + { + /* + * При push в текущий tail записывается + * сначала указатель на следующий элемент, + * после чего записывается *payload. + * Тут обрабатываем невозможную ситуацию + */ + abort(); + } + + // Больше некому прочитать этот элемент, удаляем + free(tailIn); + tailIn = newTail; + } + + return 0; +} + +``` \ No newline at end of file diff --git a/src/main.c b/src/main.c index ee8442e..b0975de 100644 --- a/src/main.c +++ b/src/main.c @@ -78,20 +78,6 @@ int main(int argc, char** argv) } } - int* ii = malloc(sizeof(int)); - if(ii == NULL) - { - abort(); - } - *ii = 0; - - int excode = ptQueuePush(qOut, ii, errbuf); - if(excode) - { - printf("Unable to push 0: %s\n", errbuf); - abort(); - } - ptQueueElem* tailIn = qIn->tail; while (1) @@ -108,22 +94,22 @@ int main(int argc, char** argv) int* pass = malloc(sizeof(int)); - if(pass != NULL) + if(pass == NULL) { - *pass = *code; - int excode = ptQueuePush(qOut, pass, errbuf); - if(excode) - { - abort(); - } + abort(); } - - if(*code == 0) + *pass = *code; + int excode = ptQueuePush(qOut, pass, errbuf); + if(excode) + { + abort(); + } + + + if(*code == 4095) { - free(payload); break; } - free(payload); ptQueueElem* newTail = atomic_load(&(tailIn->nextEl)); if (newTail == NULL) { @@ -131,8 +117,31 @@ int main(int argc, char** argv) } free(tailIn); tailIn = newTail; + + + excode = ptQueuePush(qOut, payload, errbuf); + if(excode) + { + printf("Unable to push: %s\n", errbuf); + abort(); + } } + int* ii = malloc(sizeof(int)); + if(ii == NULL) + { + abort(); + } + *ii = 0; + + int excode = ptQueuePush(qOut, ii, errbuf); + if(excode) + { + printf("Unable to push 0: %s\n", errbuf); + abort(); + } + + pthread_join(tid, NULL); return 0; }