File d’attente thread-safe pour plusieurs écrivains en C

Je travaille sur une application C multi-thread utilisant des pthreads. J’ai un thread qui écrit dans une firebase database (la bibliothèque de firebase database ne peut être utilisée que dans un seul thread) et plusieurs threads qui collectent des données, les traitent et doivent ensuite envoyer les résultats au thread de la firebase database pour le stockage. J’ai vu dans mentionné qu’il était “possible” de créer une queue sécurisée pour plusieurs auteurs en C, mais chaque endroit que je vois ainsi mentionné indique simplement que c’est “trop ​​compliqué pour cet exemple” et ne fait que démontrer une queue sécurisée pour un seul auteur. .

J’ai besoin des choses suivantes:

  • Insertion et retrait efficaces. Je suppose que comme toute autre queue, la mise en queue et la mise en queue O (1) sont possibles.
  • Mémoire allouée dynamicment, c’est-à-dire une structure liée. Je n’ai pas besoin de limite arbitraire sur la taille de la queue, donc un tableau n’est vraiment pas ce que je recherche.

EDIT: Les threads de lecture ne doivent pas tourner sur une file vide, car il est probable que le temps imparti ne dépasse pas une minute, avec de courtes rafales de grand nombre d’écritures.

Bien sûr, il y a des files d’attente sans locking. Toutefois, en fonction de ce que vous avez dit dans les commentaires, les performances ne sont pas du tout critiques, car vous créez de toute façon un fil par écriture.

Il s’agit donc d’un cas d’utilisation standard pour une variable de condition. Créez-vous une structure contenant un mutex, une variable de condition, une liste chaînée (ou un tampon circulaire si vous préférez) et un indicateur d’annulation:

write: lock the mutex (optionally - check the cancel flag to prevent leaks of stuff on the list) add the event to the list signal the condition variable unlock the mutex read: lock the mutex while (list is empty AND cancel is false): wait on the condition variable with the mutex if cancel is false: // or "if list non-empty", depending on cancel semantics remove an event from the list unlock the mutex return event if we have one, else NULL meaning "cancelled" cancel: lock the mutex set the cancel flag (optionally - dispose of anything on the list, since the reader will quit) signal the condition variable unlock the mutex 

Si vous utilisez une liste avec des nœuds externes, vous souhaiterez peut-être allouer la mémoire en dehors du verrou mutex, afin de réduire le temps de conservation. Mais si vous concevez les événements avec un nœud de liste intrusif, c’est probablement le plus simple.

Éditer: vous pouvez également prendre en charge plusieurs lecteurs (sans garantie portable pour un événement donné) si vous annulez le “signal” en “diffusion”. Bien que vous n’en ayez pas besoin, cela ne coûte rien non plus.

Si vous n’avez pas besoin d’une queue sans verrou, vous pouvez simplement envelopper une file existante avec un verrou.

 Mutex myQueueLock; Queue myQueue; void mtQueuePush(int value) { lock(myQueueLock); queuePush(myQueue, value); unlock(myQueueLock); } int mtQueueNext() { lock(myQueueLock); int value = queueFront(myQueue); queuePop(myQueue); unlock(myQueueLock); return value; } 

Il ne rest plus qu’à append une sorte de gestion pour mtQueueNext lorsque la file d’attente est vide.

ÉDITER: Si vous n’avez qu’un seul lecteur, une file d’attente sans locking à un seul écrivain, il vous suffit de verrouiller mtQueuePush pour éviter la création simultanée de plusieurs écrivains.

Il existe un nombre limité de files d’attente sans lecteur / graveur à lecteur unique, mais la plupart d’entre elles sont implémentées sous forme de classes de modèles c ++. Cependant, effectuez une recherche google et, si besoin est, trouvez comment les réécrire en clair C.

http://www.liblfds.org

Bibliothèque de structure de données sans locking écrite en C.

A la queue M & S.

Je choisirais plusieurs files d’attente pour un seul auteur (une par thread d’écrivain). Ensuite, vous pourrez vérifier comment faire en sorte que le lecteur unique lise les différentes files d’attente.