c++ - What is the difference between passing a loop counter or range-declaration to a thread by reference? -
#include <iostream> #include <memory> #include <vector> #include "boost/thread.hpp" using boost::thread; using std::vector; using std::unique_ptr; class threadpool { public: threadpool(int size) : max_size_(size) {} ~threadpool() { join(); } void pollforspace() { while (static_cast<int>(pool_.size()) >= max_size_) { (auto = pool_.begin(); != pool_.end(); ++it) { if ((*it)->timed_join(boost::posix_time::milliseconds(10))) { pool_.erase(it); break; } } } } void addtopool(unique_ptr<thread> t) { pool_.push_back(std::move(t)); } void join() { (auto = pool_.begin(); != pool_.end(); ++it) { (*it)->join(); } pool_.clear(); } protected: vector<unique_ptr<thread> > pool_; int max_size_; }; int main(int argc, char** argv) { threadpool pool(20); std::vector<int> integers; (int = 0; < 100; ++i) { integers.push_back(i); } std::cout << "range based loop on vector." << std::endl; (auto const& : integers) { pool.pollforspace(); pool.addtopool(unique_ptr<thread>(new thread([&i]{ std::cout << << std::endl; }))); } pool.join(); std::cout << "integer loop." << std::endl; (int = 0; < 100; ++i) { pool.pollforspace(); pool.addtopool(unique_ptr<thread>(new thread([&i]{ std::cout << << std::endl; }))); } pool.join(); return 0; }
why range-based for-loop print out numbers 0-99 (although not in order, , newlines interspersed incorrectly), integer loop causes print out this:
1 2 3 4 5 6 7 8 9 13 1414 14 14 15 16 18 18 19 ... 99 100
as understand it, integer being passed reference thread, value changed in main loop before thread gets print out, causing values not printed out, values printed out more once, , value 100 printed, though i
obtains value after last thread created.
however, don't see why not issue when using range-based for-loop.
why range-based for-loop version not suffer same concurrency issues plain integer loop in code?
for (int = 0; < 100; ++i) { pool.pollforspace(); pool.addtopool(unique_ptr<thread>(new thread([&i]{ std::cout << << std::endl; }))); }
you're capturing variable lambda reference. threads have reference same instance of i, you're changing in loop. you've mentioned you're aware of happening
your range based approach has vector discrete instances of aren't changing in loop.
it unrolls this:
for (auto itr = begin(integers); itr != end(integers); ++itr) { int const& = *itr; // pass new reference each thread pool.pollforspace(); pool.addtopool(unique_ptr<thread>(new thread([&i]{ std::cout << << std::endl; }))); }
you can't reseat reference in c++
Comments
Post a Comment