I am currently learning to handle concurrency in C++11 and beyond. As a reference, I chose a book called "C++ concurrency in action" which mentions that, when one designs parallel algorithms for, say, implementing a parallel accumulation of elements in a container, careful attention must be paid to the exception safety. Specifically, that the current struct:
template<typename Iterator,typename T>
struct accumulate_block
{
void operator()(Iterator first,Iterator last,T& result)
{
result=std::accumulate(first,last,result);
}
};
if called upon in the below parallel function:
template<typename Iterator,typename T>
T parallel_accumulate(Iterator first,Iterator last,T init)
{
// some code....
std::vector<T> results(num_threads);
std::vector<std::thread> threads(num_threads-1);
Iterator block_start=first;
for(unsigned long i=0;i<(num_threads-1);++i)
{
Iterator block_end=block_start;
std::advance(block_end,block_size);
threads[i]=std::thread(
accumulate_block<Iterator,T>(),
block_start,block_end,std::ref(results[i]));
block_start=block_end;
}
// more code...
}
It is argued that such code is not exception-safe because std::accumulate in the struct might throw, and proposes to use packaged_tasks and std::futures to haul exceptions between threads, rather than the above implementation.
My point is: how can I gauge which methods in the STL will throw, and how does "hauling" them inside futures and packaged_tasks make them any safer?
Thanks
Amine
Aucun commentaire:
Enregistrer un commentaire