deque::push_back с потоками странно реагирует
Я пробовал разные вещи, но push_back потоков в контейнере deque реагирует странно.
почему это происходит?? Это из-за конструкторов копирования / перемещения?
Вот вывод программы...
progress[0]:-1
progress[1]:-1
executing threads...
progress[0]:100
progress[1]:100
================================
progress[0]:-1
progress[1]:-1
executing threads...
progress[0]:-1
progress[1]:100
Как видно из результатов, результат откладывается между использованием
for(size_t i = 0; i < 2; ++i) {
deq.push_back(th(&progress[i]));
}
а также
deq.push_back(th(&progress[0]));
deq.push_back(th(&progress[1]));
Это исходный код...
class th {
public:
void func() {
*this->progress = 100;
}
th(int* prog) :
progress(prog),
m_thread(std::thread(&th::func, this)) {};
// COPY
th(th const& other);
th& operator=(th const& other);
// MOVE
th(th&&) = default;
// th& operator=(th&& other) {
// if(this != &other){
// }
// return *this;
// }
void join() { m_thread.join(); }
int *progress;
private:
std::thread m_thread;
};
int main(void) {
{
std::vector<int> progress;
progress.push_back(-1);
progress.push_back(-1);
std::deque<th> deq;
std::cout << "progress[0]:" << progress[0] << std::endl;
std::cout << "progress[1]:" << progress[1] << std::endl;
std::cout << "executing threads..." << std::endl;
deq.push_back(th(&progress[0]));
deq.push_back(th(&progress[1]));
for (std::deque<th>::iterator it = deq.begin(); it != deq.end(); it++) {
it->join();
// deq.erase(it);
}
std::cout << "progress[0]:" << progress[0] << std::endl;
std::cout << "progress[1]:" << progress[1] << std::endl;
}
std::cout << "================================" << std::endl;
{
std::vector<int> progress;
progress.push_back(-1);
progress.push_back(-1);
std::deque<th> deq;
std::cout << "progress[0]:" << progress[0] << std::endl;
std::cout << "progress[1]:" << progress[1] << std::endl;
std::cout << "executing threads..." << std::endl;
for(size_t i = 0; i < 2; ++i) {
deq.push_back(th(&progress[i]));
}
for (std::deque<th>::iterator it = deq.begin(); it != deq.end(); it++) {
it->join();
// deq.erase(it);
}
std::cout << "progress[0]:" << progress[0] << std::endl;
std::cout << "progress[1]:" << progress[1] << std::endl;
}
exit(EXIT_SUCCESS);
}
И как я могу использовать функцию стирания члена deque без жалоб компилятора
/home/user/test/obj/main.o: In function `__gnu_cxx::_Mutable_BidirectionalIteratorConcept<th*>::__constraints()':
main.cpp:(.text._ZN9__gnu_cxx37_Mutable_BidirectionalIteratorConceptIP2thE13__constraintsEv[__gnu_cxx::_Mutable_BidirectionalIteratorConcept<th*>::__constraints()]+0x40): undefined reference to `th::operator=(th const&)'
/home/user/test/obj/main.o: In function `__gnu_cxx::_ConvertibleConcept<th, th>::__constraints()':
main.cpp:(.text._ZN9__gnu_cxx19_ConvertibleConceptI2thS1_E13__constraintsEv[__gnu_cxx::_ConvertibleConcept<th, th>::__constraints()]+0x20): undefined reference to `th::th(th const&)'
/home/user/test/obj/main.o: In function `__gnu_cxx::_OutputIteratorConcept<th*, th>::__constraints()':
main.cpp:(.text._ZN9__gnu_cxx22_OutputIteratorConceptIP2thS1_E13__constraintsEv[__gnu_cxx::_OutputIteratorConcept<th*, th>::__constraints()]+0x64): undefined reference to `th::operator=(th const&)'
/home/user/test/obj/main.o: In function `th* std::__copy_move_backward<true, false, std::random_access_iterator_tag>::__copy_move_b<th*, th*>(th*, th*, th*)':
main.cpp:(.text._ZNSt20__copy_move_backwardILb1ELb0ESt26random_access_iterator_tagE13__copy_move_bIP2thS4_EET0_T_S6_S5_[th* std::__copy_move_backward<true, false, std::random_access_iterator_tag>::__copy_move_b<th*, th*>(th*, th*, th*)]+0x5c): undefined reference to `th::operator=(th const&)'
/home/user/test/obj/main.o: In function `th* std::__copy_move<true, false, std::random_access_iterator_tag>::__copy_m<th*, th*>(th*, th*, th*)':
main.cpp:(.text._ZNSt11__copy_moveILb1ELb0ESt26random_access_iterator_tagE8__copy_mIP2thS4_EET0_T_S6_S5_[th* std::__copy_move<true, false, std::random_access_iterator_tag>::__copy_m<th*, th*>(th*, th*, th*)]+0x44): undefined reference to `th::operator=(th const&)'
/home/user/test/obj/main.o: In function `__gnu_cxx::_Mutable_ForwardIteratorConcept<th*>::__constraints()':
main.cpp:(.text._ZN9__gnu_cxx31_Mutable_ForwardIteratorConceptIP2thE13__constraintsEv[__gnu_cxx::_Mutable_ForwardIteratorConcept<th*>::__constraints()]+0x3c): undefined reference to `th::operator=(th const&)'
collect2: ld returned 1 exit status
make: *** [link] Error 1
Спасибо!
1 ответ
Вы передаете значение this
(т.е. текущий адрес объекта) в конструктор std::thread
, После перемещения th
объект в deque, это значение this
больше не действителен, так как объект теперь перемещен в другое место. Тем не менее, поток все еще использует старое значение. Попробуйте сделать th
неподвижный и использующий emplace_back
скорее, чем push_back
,
class th {
public:
void func() {
*this->progress = 100;
}
explicit th(int* prog) :
progress(prog),
m_thread(std::thread(&th::func, this)) {};
// COPY
th(th const& other) = delete;
th(th && other) = delete;
th& operator=(th const& other) = delete;
th& operator=(th &&) = delete;
void join() { m_thread.join(); }
int *progress;
private:
std::thread m_thread;
};
std::vector<int> progress;
progress.push_back(-1);
progress.push_back(-1);
std::deque<th> deq;
deq.emplace_back (&progress[0]);
// etc.