Implémentation d'un compteur atomique 64 bits avec des variables atomiques 32 bits
Question :
Concevoir et implémenter un compteur atomique 64 bits utilisant des variables atomiques 32 bits. Le compteur a un seul écrivain (gestionnaire de signal) et plusieurs lecteurs.
Code :
class counter { atomic<uint32_t> lo_{}; atomic<uint32_t> hi_{}; atomic<uint32_t> gen_{}; uint64_t read() const { auto acquire = memory_order_acquire; uint32_t lo, hi, gen1, gen2; do { gen1 = gen_.load(acquire); lo = lo_.load(acquire); hi = hi_.load(acquire); gen2 = gen_.load(acquire); } while (gen1 != gen2 || (gen1 & 1)); return (uint64_t(hi) << 32) | lo; } void increment() { auto release = memory_order_release; gen_.fetch_add(1, release); uint32_t newlo = 1 + lo_.fetch_add(1, release); if (newlo == 0) { hi_.fetch_add(1, release); } gen_.fetch_add(1, release); } };
Réponse :
Le code fourni est une implémentation correcte d'un compteur atomique 64 bits utilisant des variables atomiques 32 bits. Il utilise une technique connue sous le nom de SeqLock, qui utilise un décompte de générations pour maintenir la cohérence des moitiés haute et basse du compteur.
L'opération de lecture utilise une boucle pour acquérir l'état correct du compteur lors de la manipulation. conditions de course potentielles entre lecteurs et écrivains. L'opération d'écriture incrémente atomiquement les parties haute et basse du compteur, en utilisant l'ordre de la mémoire pour garantir un comportement correct.
Implémentation améliorée :
Bien que le code fourni soit correct , il peut être amélioré pour de meilleures performances et efficacité :
Conception alternative :
Une conception alternative qui élimine complètement le besoin d'opérations RMW atomiques consiste à utiliser une union d'un élément volatile uint64_t et un std::atomic Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!