Maison >développement back-end >C++ >Comment implémenter un compteur atomique 64 bits en utilisant uniquement des variables atomiques 32 bits ?

Comment implémenter un compteur atomique 64 bits en utilisant uniquement des variables atomiques 32 bits ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-12-11 17:38:19717parcourir

How to Implement a 64-bit Atomic Counter Using Only 32-bit Atomic Variables?

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é :

  • Au lieu d'utiliser des opérations RMW atomiques pour la charge utile du compteur, elles peuvent être remplacées avec des charges et des magasins simples pour éviter des frais généraux inutiles.
  • Le compteur de séquence peut également être maintenu avec des charges et des magasins simples, car il doit seulement être augmenté de manière monotone et non mis à jour de manière atomique.

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 variable. La partie volatile peut être utilisée pour lire et écrire la valeur, tandis que la variable atomique peut être utilisée pour mettre à jour le compteur de séquence. Cette approche apporte les garanties nécessaires à un comportement correct tout en optimisant les performances.

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn