1

J'utilise le Runtime Concurrency avec Visual C++ 2010, et je suis intéressé par les capacités de parallel_invoke et task_group (parties de la PPL ou Parallel Patterns Library). Je voudrais être en mesure de démarrer deux actions parallèles via des objets de fonction (plutôt que des fonctions lambda ou des pointeurs de fonction), mais je ne peux pas obtenir le code à compiler, en raison d'une erreur:Dans le Runtime de Concurrency, puis-je utiliser parallel_invoke ou task_group avec des objets fonction non-const?

error C3848: expression having type 'const C' would lose some const-volatile qualifiers in order to call 'void C::operator()(void)' 

Mais si Je fais le C :: operator()() const, alors je perds beaucoup des avantages d'un objet fonction, à savoir, que son état est mutable et maintenu en interne entre les appels. Est-ce que j'ai râté quelque chose? Existe-t-il un moyen d'invoquer des objets fonction non-const en parallèle? Par ailleurs, je me rends compte que je pourrais utiliser le Asynchronous Agents Library, et dériver les classes de la classe Concurrency :: agent, mais veuillez considérer cela au-delà de la portée de cette question (en partie en raison du manque de gestion des exceptions et des options d'annulation). Je m'intéresse simplement à ce que je peux faire avec la PPL, et bien qu'il y ait des exemples avec des fonctions lambda et des pointeurs de fonction, je n'ai pas pu trouver ou créer d'exemples avec des objets fonctionnels qui font plus qu'un parallèle Monde". Je cherche quelque chose qui tire vraiment parti des objets de fonction, et, si possible, également des conteneurs concurrents.

Répondre

2

Les foncteurs doivent être immuables car lorsqu'ils sont programmés via parallel_invoke et task_group :: run, ils sont copiés et le potentiel de conditions de course pendant les accumulations d'états est élevé. Particulièrement avec task_group :: run la durée de vie de la tâche a le potentiel de survivre là où la tâche a été déclarée (ie la déclare sur la pile et la pile se termine mais la tâche n'est pas encore exécutée)

La technique la plus simple peut être utilisé pour contourner ce problème est de capturer le foncteur par référence dans un lambda (oui je sais que vous avez dit que vous ne vouliez pas utiliser lambdas directement).

NonConstFunctor func; 
    Concurrency::task_group tasks; 
    // c3848 
    //tasks.run(func); 
    //work around this by capturing func by reference 
    tasks.run([&func](){func();}); 

Vous pouvez également utiliser les installations « tâche légère » de la classe de programmation (voir Scheduler :: scheduleTask) qui ne nécessite pas const car il a une API typique de vide *.

Vous aurez besoin de construire une fonction enveloppe pour gérer, mais cela est simple et il y a un dans le pack d'échantillons à http://code.msdn.com/concrtextras

-Rick

+0

Pourriez-vous terminer cette deuxième phrase. Il se termine par "potentiel de survivre à", vraisemblablement foncteur. BTW, a regardé certaines de vos vidéos sur Channel 9 récemment, et les aime. Excellent travail, et merci d'avoir regardé le forum de stackoverflow! –

0

Pourquoi ne pas simplement faire l'opérateur()() const et use mutable pour garder l'état? Mais, bien sûr, vous courez des risques sérieux ici, parce que vous seriez responsable de tous les problèmes liés à la sécurité des threads avec la mutation de cet état. Ces objets de fonction ne sont pas supposés le faire.

Modifier: Sérieusement. Utilisez juste des lambdas. Les objets de fonction sont morts dans VS2010. Pourquoi un code postal de compilateur C++ 0x devrait-il indiquer l'idiome de fonction du passé qu'ils ont passé le temps et l'argent remplaçant? C'est contradictoire et fou.

+0

Oui, il suffit d'utiliser lambdas; C'est ce qu'ils sont là pour ça. Quand les lambdas ne fonctionnent pas, revenez aux foncteurs roulés à la main ... – Rick

+0

Eh bien, je dois avouer que je suis un peu en retard.Ayant lu un peu plus sur lambdas, je suis très excité par eux. Merci à vous deux d'avoir poussé dans cette direction. –