I've got this thread pool that holds a container of objects, and whenever it receives a new piece of data, it updates all the objects with the same new piece of data. The work is preallocated on the construction of the thread pool, and this work is stored in the following data member
std::map<std::thread::id, std::vector<unsigned>> m_work_schedule
So if a thread's element in this map
has the elements 1,2 and 3 in its vector<unsigned>
, that means it is responsible for updating the objects with indexes 1,2 and 3 every time a new data point arrives.
If I have ten objects and three threads, the work schedule might look something like this
140314357151488... 2, 5, 8,
140314365544192... 1, 4, 7,
140314373936896... 0, 3, 6, 9,
In every worker thread , it does some calculation and then adds its calculation to the shared aggregate variable. I'm confused though, because once all the threads are finished, only the final thread is supposed to put the finishing touches on the calculation. For some reason, this block is occasionally executing twice:
if( std::prev(m_work_schedule.end())->first == std::this_thread::get_id() ){
std::cout << "about to finalize from thread " << std::this_thread::get_id() << ", which supposedly is equal to " << (--m_work_schedule.end())->first << "\n";
m_working_agg = m_final_f(m_working_agg);
m_out.set_value(m_working_agg);
}
The output looks like this:
139680503645952... 2, 5, 8,
139680512038656... 1, 4, 7,
139680520431360... 0, 3, 6, 9,
about to finalize from thread 139680520431360, which supposedly is equal to 139680520431360
................
about to finalize from thread 139680503645952, which supposedly is equal to 139680503645952
terminate called after throwing an instance of 'std::future_error'
what(): std::future_error: Promise already satisfied
How can this block of code run twice, though? I am only reading from m_work_schedule
, but the occasional nature of this suggests it's some sort of race condition. I'm struggling to think of any possible explanation for this, though.
std::map::end()
return different things in different threads? std::map::end()
affect another thread's?**I bet your problem is here
for(unsigned i=0; i< m_num_threads; ++i) {
m_threads.push_back( std::thread(&split_data_thread_pool::worker_thread, this));
most_recent_id = m_threads.back().get_id();
m_work_schedule.insert(std::pair<std::thread::id, std::vector<unsigned> >(most_recent_id, std::vector<unsigned>{}));
m_has_new_dyn_input.insert(std::pair<std::thread::id, bool>(most_recent_id, false));
}
you are starting the threads while you are still populating the m_work_schedule_map. And as far as I can see there is no lock. So you have simultaneous readers and writers
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.