web-dev-qa-db-fra.com

Est-il judicieux de remplacer boost :: thread et boost :: mutex par des équivalents de c ++ 11?

Motivation: la raison pour laquelle je pense que c'est parce que mon chef de projet de génie pense que le boost est une autre dépendance et que c'est horrible parce que "vous en dépendez" (j'ai essayé d'expliquer la qualité du boost, puis j'ai abandonné au bout d'un moment :( La plus petite raison pour laquelle je voudrais le faire est que j’aimerais apprendre les fonctionnalités de c ++ 11, car les gens commenceront à écrire du code dans celui-ci.

  1. Y a-t-il une correspondance 1: 1 entre #include<thread> #include<mutex>et augmenter les équivalents?
  2. Envisageriez-vous une bonne idée de remplacer les éléments boost par c ++ 11
    des trucs. Mon utilisation est primitive, mais existe-t-il des exemples de situations où std n'offre pas ce boost? Ou (blasphème) vice versa?

P.S. J'utilise GCC alors les en-têtes sont là.

149
NoSenseEtAl

Il existe plusieurs différences entre Boost.Thread et la bibliothèque de threads standard C++ 11:

  • Boost prend en charge l'annulation de threads, pas les threads C++ 11
  • C++ 11 prend en charge std::async, Mais pas Boost
  • Boost a un boost::shared_mutex Pour le verrouillage à plusieurs lecteurs/un seul auteur. L’analogue std::shared_timed_mutex N’est disponible que depuis C++ 14 ( N3891 ), tandis que std::shared_mutex N’est disponible que depuis C++ 17 ( N4508 =).
  • Les délais d'attente C++ 11 sont différents de ceux de Boost (bien que cela devrait bientôt changer, Boost.Chrono a été accepté).
  • Certains noms sont différents (par exemple, boost::unique_future Vs std::future)
  • La sémantique de passage d'arguments de std::thread Est différente de boost::thread --- Boost utilise boost::bind, Ce qui nécessite des arguments copiables. std::thread Permet aux types de déplacement uniquement tels que std::unique_ptr D'être transmis en tant qu'arguments. En raison de l'utilisation de boost::bind, La sémantique des espaces réservés tels que _1 Dans les expressions de liaison imbriquées peut également être différente.
  • Si vous n'appelez pas explicitement join() ou detach(), le destructeur boost::thread Et l'opérateur d'affectation appellent detach() sur l'objet de thread en cours de destruction/assigné à. Avec un objet C++ 11 std::thread, Il en résultera un appel à std::terminate() et un abandon de l'application.

Pour clarifier le point concernant les paramètres de déplacement uniquement, ce qui suit est valide C++ 11 et transfère la propriété du int du temporaire std::unique_ptr Au paramètre de f1 lorsque le nouveau thread est démarré. Cependant, si vous utilisez boost::thread, Cela ne fonctionnera pas, car il utilise boost::bind En interne et std::unique_ptr Ne peut pas être copié. Il existe également un bogue dans la bibliothèque de threads C++ 11 fournie avec GCC qui empêche ce fonctionnement, car il utilise également std::bind Dans son implémentation.

void f1(std::unique_ptr<int>);
std::thread t1(f1,std::unique_ptr<int>(new int(42)));

Si vous utilisez Boost, vous pouvez probablement passer aux threads C++ 11 de manière relativement simple si votre compilateur le supporte (par exemple, les versions récentes de GCC sur Linux ont une implémentation presque complète de la bibliothèque de threads C++ 11 disponible dans -std=c++0x).

Si votre compilateur ne prend pas en charge les threads C++ 11, vous pourrez peut-être obtenir une implémentation tierce telle que Just :: Thread , mais il s'agit toujours d'une dépendance.

186
Anthony Williams

std::thread est largement inspiré de boost::thread, avec quelques différences :

  • la sémantique non optimisée de one-handle-maps-to-one-os-thread de boost est conservée. Mais ce fil est mobile pour permettre le retour du fil des fonctions d'usine et son placement dans des conteneurs.
  • Cette proposition ajoute l'annulation à la boost::thread, qui est une complication significative. Cette modification a un impact important non seulement sur les threads, mais également sur le reste de la bibliothèque de threads C++. On pense que ce changement important est justifiable en raison des avantages.
    • Le destructeur de threads doit maintenant appeler cancel avant de détacher pour éviter une fuite accidentelle de threads enfants lorsque les threads parents sont annulés.
    • Un membre de détachement explicite est maintenant requis pour permettre le détachement sans annuler.
  • Les concepts de handle de thread et d'identité de thread ont été séparés en deux classes (il s'agit de la même classe dans boost::thread). Cela facilite la manipulation et le stockage de l'identité du fil.
  • La possibilité de créer un identifiant de thread dont la comparaison est garantie à aucun autre thread pouvant être joint n'a été ajoutée (boost::thread n'a pas cela). C'est pratique pour le code qui veut savoir s'il est exécuté par le même thread qu'un appel précédent (les mutex récursifs en sont un exemple concret).
  • Il existe une "porte dérobée" pour obtenir le descripteur de thread natif afin que les clients puissent manipuler les threads à l'aide du système d'exploitation sous-jacent, le cas échéant.

C’est à partir de 2007, certains points ne sont donc plus valides: boost::thread a un native_handle fonctionne maintenant et, comme le soulignent les commentateurs, std::thread n'a plus d'annulation.

Je n'ai trouvé aucune différence significative entre boost::mutex et std::mutex.

23
Alex B

cas d'entreprise

Si vous écrivez un logiciel pour une entreprise devant fonctionner sur une grande variété de systèmes d’exploitation et, par conséquent, compiler avec divers compilateurs et versions de compilateur (en particulier des versions relativement anciennes) sur ces systèmes d’exploitation, ma suggestion est de rester à l’écart. C++ 11 tout à fait pour le moment. Cela signifie que vous ne pouvez pas utiliser std::thread, et je recommanderais d'utiliser boost::thread.

Cas de démarrage Basic/Tech

Si vous écrivez pour un ou deux systèmes d’exploitation, vous êtes certain de ne jamais avoir besoin de compiler avec un compilateur moderne qui supporte principalement C++ 11 (par exemple, VS2015, GCC 5.3, Xcode 7), et vous n’êtes pas déjà dépendant de la bibliothèque de boost, puis std::thread pourrait être une bonne option.

Mon expérience

Personnellement, je préfère les bibliothèques renforcées, fortement utilisées, très compatibles et très cohérentes telles que boost par rapport à une alternative très moderne. Cela est particulièrement vrai pour les sujets de programmation complexes tels que les threads. En outre, j'ai longtemps connu un grand succès avec boost::thread (et boost en général) dans une vaste gamme d’environnements, de compilateurs, de modèles de threads, etc. Lorsque c’est mon choix, je choisis boost.

6
Nicholas Smith

Il y a une raison pour ne pas migrer vers std::thread.

Si vous utilisez des liens statiques, std::thread devient inutilisable à cause de ces bogues/caractéristiques de gcc:

À savoir, si vous appelez std::thread::detach ou std::thread::join cela entraînera une exception ou un crash, alors que boost::thread fonctionne bien dans ces cas.

6
ks1322

Avec Visual Studio 2013, le std::mutex semble se comporter différemment du boost::mutex, ce qui m'a causé quelques problèmes (voir cette question ).

3
Robert Hegner

En ce qui concerne std :: shared_mutex ajouté en C++ 17

Les autres réponses ici donnent un très bon aperçu des différences en général. Cependant, il existe plusieurs problèmes avec std::shared_mutex Que boost résout.

  1. Mutices améliorables. Ceux-ci sont absents de std::thread. Ils permettent à un lecteur d'être mis à niveau vers un rédacteur sans permettre à aucun autre rédacteur d'entrer avant vous . Celles-ci vous permettent d'effectuer des opérations telles que le prétraitement d'un calcul volumineux (par exemple, la réindexation d'une structure de données) en mode lecture, puis la mise à niveau en écriture pour appliquer la réindexation tout en maintenant le verrou en écriture pendant une courte période.

  2. Justice. Si vous avez une activité de lecture constante avec un std::shared_mutex, Vos rédacteurs seront verrouillés pour une durée indéterminée. En effet, si un autre lecteur se présente, il aura toujours la priorité. Avec boost:shared_mutex, La priorité sera donnée à tous les threads .(1) Ni les lecteurs ni les écrivains ne seront affamés.

Le problème, c’est que si vous avez un système à très haut débit, sans temps d’immobilisation ni conflit important, std::shared_mutex Ne fonctionnera jamais pour vous sans la construction manuelle d’un système de priorité. boost::shared_mutex Fonctionnera immédiatement, mais vous aurez peut-être besoin de le modifier dans certains cas. Je dirais que le comportement de std::shared_mutex Est un bogue latent en attente dans la plupart des codes qui l'utilisent.

(1)Le algorithme qu'il utilise est basé sur le planificateur de threads du système d'exploitation. D'après mon expérience, lorsque les lectures sont saturées, les pauses sont plus longues (lors de l'obtention d'un verrou en écriture) sous Windows que sous OSX/Linux.

1
Robert Fraser

J'ai essayé d'utiliser shared_ptr à partir de std au lieu de boost et j'ai trouvé un bogue dans l'implémentation gcc de cette classe. Mon application se bloquait à cause d'un destructeur appelé deux fois (cette classe devrait être thread-safe et ne devrait pas générer de tels problèmes). Après avoir déplacé boost :: shared_ptr, tous les problèmes ont disparu. Les implémentations actuelles de C++ 11 ne sont toujours pas mûres.

Boost a également plus de fonctionnalités. Par exemple, l'en-tête dans la version std ne fournit pas de sérialiseur à un flux (c'est-à-dire cout << durée). Boost a beaucoup de bibliothèques qui utilisent ses propres équivalents, etc., mais ne coopèrent pas avec les versions std.

Pour résumer, si vous avez déjà une application écrite avec boost, il est préférable de conserver votre code tel quel au lieu de faire des efforts pour passer à la norme C++ 11.

0
user3323559