Могу ли я использовать в Concurrency Runtime параллель_invoke или task_group с объектами неконстантных функций? - PullRequest
1 голос
/ 12 ноября 2010

Я использую Concurrency Runtime с Visual C ++ 2010 и мне интересны возможности parallel_invoke и task_group (части PPL или Parallel Patterns Library ). Я хотел бы иметь возможность запускать два параллельных действия через функциональные объекты (а не лямбда-функции или указатели функций), но я не могу заставить код компилироваться из-за ошибки:

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

Но если я сделаю C :: operator () () const, то я потеряю много преимуществ функционального объекта, а именно то, что его состояние является изменяемым и поддерживается внутри между вызовами. Я что-то здесь упускаю? Есть ли способ, которым я мог бы вызывать объекты неконстантных функций параллельно?

Кстати, я понимаю, что могу использовать библиотеку Asynchronous Agents Library и извлечь классы из класса Concurrency :: agent, но учтите, что это выходит за рамки этого вопроса (частично из-за отсутствие обработки исключений и параметров отмены).

Мне просто интересно, что я могу сделать с PPL, и хотя есть примеры с лямбда-функциями и указателями на функции, я не смог найти или создать какие-либо примеры с объектами функций, которые делают больше, чем параллельный «Hello World» ». Я ищу что-то, что действительно использует в своих интересах функциональные объекты, и, если возможно, также параллельные контейнеры.

Ответы [ 2 ]

2 голосов
/ 15 ноября 2010

Функторы должны быть неизменяемыми, потому что, когда они планируются через параллельные_инвойны и task_group :: run, они копируются, и вероятность возникновения состояний гонки во время накопления состояний высока.В частности, с помощью task_group :: run время жизни задачи может пережить место, где была объявлена ​​задача (т. Е. Вы объявляете ее в стеке, и стек выходит, но задача еще не запущена)

Самый простойЧтобы обойти это, можно использовать метод захвата функтора по ссылке в лямбде (да, я знаю, вы сказали, что не хотите использовать лямбды напрямую).

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

Вы также можете использоватьсредства 'облегченной задачи' класса планировщика (см. Scheduler :: ScheduleTask), для которых не требуется const, поскольку он имеет типичный void * API.

Вам потребуется создать функцию-обертку для обработки этого, но это просто и есть один в пакете образцов в http://code.msdn.com/concrtextras

-Rick

0 голосов
/ 15 ноября 2010

Почему бы просто не сделать оператор () () const и использовать изменяемый для сохранения состояния?

Но, конечно, вы здесь рискуете серьезными, потому что вы будете нести ответственность за все проблемы, связанные с безопасностью потоков, с изменением этого состояния. Эти функциональные объекты не должны этого делать.

Редактировать: Серьезно. Просто используйте лямбды. Функциональные объекты мертвы в VS2010. Почему компилятор C ++ 0x должен публиковать код, показывающий идиомы функций прошлого, которые они потратили на замену времени и денег? Это противоречиво и безумно.

...