Programmation multi-cœurs

Nous allons implémenter un buffer circulaire qui permet à un lecteur et un écrivain d'échanger des données ordonnées sans utiliser de verrou ni de mémoire allouée dynamiquement.

Ce buffer circulaire offre les possibilités suivantes :

  • L'initialisation se fait à partir d'un tableau de données non initialisées ou à partir d'un pointeur brut et d'une longueur qui représentent l'espace de stockage utilisé par le buffer circulaire.
  • Le buffer est utilisable par un lecteur et un écrivain à la fois, aucun ne pouvant bloquer l'autre.
  • Lorsqu'on veut ajouter des éléments, ils sont soit tous rajoutés soit aucun en cas de manque de place. Des éléments multiples peuvent être ajoutés avec push_all() à partir de n'importe quel itérateur qui implémente ExactSizeIterator afin de pouvoir procéder à la vérification.
  • Les éléments sont soit récupérés un par un avec pop().
  • Deux méthodes execute() et execute_max() permettent d'appliquer une fonction à une vue partielle du buffer circulaire. Les éléments sont présentés sous la forme d'une référence sur une slice et sont considérés pouvoir être libérés une fois que la fonction retourne.
  • Les références sur le buffer implémentent Iterator et renvoient les éléments disponibles.

Étant donné la taille du code, vous disposez d'un projet disponible ici. Ce projet est à compléter partout où se trouvent des todo!(). Des tests permettent de vérifier le bon comportement du buffer circulaire une fois les fonctions manquantes implémentées.