97 lines
3.0 KiB
Markdown
97 lines
3.0 KiB
Markdown
# ptQueue
|
||
Сищная либа для "потокобезопасных" очередей на односвязном списке для ситуаций когда есть только один писатель.
|
||
После передачи объекта в очередь, писатель теряет владение объектом и его управление переходит к читателю/читателям.
|
||
|
||
Как использовать:
|
||
```C
|
||
#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;
|
||
}
|
||
|
||
``` |