Files
ptQueue/README.md
2025-01-21 19:47:52 +03:00

3.0 KiB
Raw Blame History

ptQueue

Сищная либа для "потокобезопасных" очередей на односвязном списке для ситуаций когда есть только один писатель.
После передачи объекта в очередь, писатель теряет владение объектом и его управление переходит к читателю/читателям.

Как использовать:

#include <stdlib.h> // для 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;
}