Question

Comment implémentez-vous un système de comptage de références efficace et sécurisé en termes de threads sur les UC X86 en langage de programmation C ++?

Je rencontre toujours le problème suivant: les opérations critiques non atomiques et les opérations d'interverrouillage X86 disponibles ne sont pas suffisants pour mettre en œuvre le système de comptage des références.

L'article suivant traite de ce sujet, mais requiert des instructions spéciales du processeur:

http://www.ddj.com/architect/184401888

Était-ce utile?

La solution

De nos jours, vous pouvez utiliser le Boost / TR1 shared_ptr < > pointeur intelligent pour conserver vos références comptées.

fonctionne très bien; pas de chichi, pas de muss. Le shared_ptr & Lt; & Gt; La classe s'occupe de tout le verrouillage nécessaire sur le refcount.

Autres conseils

Dans VC ++, vous pouvez utiliser _InterlockedCompareExchange .

do
   read the count
   perform mathematical operation
   interlockedcompareexchange( destination, updated count, old count)
until the interlockedcompareexchange returns the success code.

Sur les autres plates-formes / compilateurs, utilisez la valeur intrinsèque appropriée pour l'instruction LOCK CMPXCHG exposée par _InterlockedCompareExchange de MS.

À proprement parler, vous devrez attendre C ++ 0x pour pouvoir écrire du code sans thread thread en C ++ pur.

Pour l'instant, vous pouvez utiliser Posix ou créer vos propres wrappers indépendants de la plate-forme pour comparer et échanger et / ou incrémenter / décrémenter.

Win32 InterlockedIncrementAcquire et InterlockedDecrementRelease (si vous voulez être sûr et soucieux des plates-formes avec possibilité de réorganisation, vous devez donc émettre des barrières de mémoire en même temps) ou InterlockedIncrement et InterlockedDecrement (si vous êtes sûr de rester x86). atomique et fera le travail.

Cela dit, Boost / TR1 shared_ptr < > gérera tout cela pour vous. Par conséquent, à moins que vous n'ayez à le mettre en œuvre vous-même, vous ferez probablement de votre mieux pour vous y tenir.

N'oubliez pas que le verrouillage est très coûteux et qu'il se produit chaque fois que vous remettez des objets entre des pointeurs intelligents, même lorsque l'objet appartient actuellement à un seul thread (la bibliothèque du pointeur intelligent ne le sait pas).

Compte tenu de cela, il peut y avoir une règle de base applicable ici (je suis heureux d'être corrigé!)

Si les éléments suivants s'appliquent à vous:

  • Vous avez des structures de données complexes pour lesquelles il serait difficile d'écrire des destructeurs (ou lorsque la sémantique des valeurs de style STL serait inappropriée, de par leur conception), vous avez donc besoin de pointeurs intelligents pour le faire à votre place et
  • vous utilisez plusieurs threads qui partagent ces objets, et
  • Vous vous souciez de la performance ainsi que de l'exactitude

... alors la collecte des ordures réelle peut être un meilleur choix. Bien que GC ait une mauvaise réputation en matière de performances, tout est relatif. Je crois que cela se compare très favorablement au verrouillage de pointeurs intelligents. C’est en partie pour cette raison que l’équipe CLR a choisi le vrai GC au lieu d’un système de comptage des références. Voir cet article , en particulier cette comparaison frappante de ce que signifie une assignation de référence si vous avoir comptage en cours:

pas de ref comptage:

a = b;

comptage des références:

if (a != null)
    if (InterlockedDecrement(ref a.m_ref) == 0)
            a.FinalRelease();

if (b != null)
    InterlockedIncrement(ref b.m_ref);

a = b;

Si l'instruction elle-même n'est pas atomique, vous devez définir la section critique de la section de code qui met à jour la variable appropriée.

i.e. Vous devez empêcher d'autres threads d'entrer cette section de code en utilisant un schéma de verrouillage. Bien sûr, les verrous doivent être atomiques, mais vous pouvez trouver un mécanisme de verrouillage atomique dans la classe pthread_mutex.

La question de l'efficacité: la bibliothèque pthread est aussi efficace que possible tout en garantissant que le verrouillage mutex est atomique pour votre système d'exploitation.

Est-ce cher? Probablement. Mais pour tout ce qui nécessite une garantie, il y a un coût.

Ce code particulier publié dans cet article de ddj ajoute une complexité supplémentaire pour rendre compte des bugs liés à l'utilisation de pointeurs intelligents.

Plus précisément, si vous ne pouvez pas garantir que le pointeur intelligent ne changera pas lors d'une affectation à un autre pointeur intelligent, vous le faites mal ou vous faites quelque chose de très peu fiable pour commencer. Si le pointeur intelligent peut changer tout en étant assigné à un autre pointeur intelligent, cela signifie que le code effectuant l'affectation ne possède pas le pointeur intelligent, ce qui est suspect pour commencer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top