c++ - thread creation with a member function runs before the object constructor finishes in for loop -
i'm coding simple client/server multithread program. client threads created like
for (int = 0; < 4; i++) { clients.emplace_back(work_finished, updated[i], free_client_count,i); client_threads.emplace_back([&] { clients[i].work(); }); }
and initiation parameters are
std::atomic_bool work_finished; work_finished.store(false); std::atomic_bool updated[4]; updated[0].store(false); updated[1].store(false); updated[2].store(false); updated[3].store(false); atomic_int free_client_count; free_client_count.store(0);
but these client threads wouldn't run expected, result in invalid memory access during update[i].load()
. if create loop create threads, there no problem.
for (int = 0; < 4; i++) { clients.emplace_back(work_finished, updated[i], free_client_count,i); } (int = 0; < 4; i++) { client_threads.emplace_back([&] { clients[i].work(); }); }
then add log information client constructor. turns out client.work()
called before constructor finishes, result in invalid memory access of update_recieved.load()
because update_recieved
not initiated yet.
here comes question: why work
called before client constructed when in same loop? , why it's right break client constructor , thread constructor. complete code below
using namespace std; class client { public: std::atomic_int& ready_thread_count; std::atomic_bool& update_recieved; std::atomic_bool& work_finished; const int i; void recieve() { try { while (!update_recieved.load()) { //std::cout << "not recieved " << << std::endl; std::this_thread::yield(); } std::cout << "recieved " << << std::endl; update_recieved.store(false); } catch (std::exception e) { std::cout << e.what() << std::endl; } } void compute() { // } void send() { ready_thread_count++; } public: client(std::atomic_bool& in_work_finished, std::atomic_bool& in_update_recieved, std::atomic_int& in_free_thread_count,int in_i) :work_finished(in_work_finished), update_recieved(in_update_recieved), ready_thread_count(in_free_thread_count), i(in_i) { std::cout << "client created " << << std::endl; } void work() { recieve(); while (!work_finished.load()) { compute(); send(); recieve(); } send(); } }; class server { public: std::atomic_int& ready_thread_count; std::atomic_bool* update_recieved_vector; std::atomic_bool& work_finished; const std::chrono::microseconds wait_time; const int client_number; int iteration; void send() { (int = 0; < client_number; i++) { std::cout << "update client " << << std::endl; update_recieved_vector[i].store(true); } } void compute() { std::this_thread::sleep_for(wait_time); iteration++; std::cout << iteration << std::endl; if (iteration == 50) { work_finished.store(true); } } void recieve() { while (ready_thread_count.load() != client_number) { std::this_thread::sleep_for(wait_time); } ready_thread_count.store(0); } public: server(std::atomic_int& in_free_thread_count, std::atomic_bool* in_update_recieved_vector, std::atomic_bool& in_work_finished, int in_client_member, int in_wait_time) :ready_thread_count(in_free_thread_count), update_recieved_vector(in_update_recieved_vector), work_finished(in_work_finished), client_number(in_client_member), wait_time(in_wait_time) { iteration = 0; } void work() { while (!work_finished.load()) { send(); recieve(); compute(); } send(); recieve(); } }; int main() { std::atomic_bool work_finished; work_finished.store(false); std::atomic_bool updated[4]; updated[0].store(false); updated[1].store(false); updated[2].store(false); updated[3].store(false); atomic_int free_client_count; free_client_count.store(0); server local_server(free_client_count, updated, work_finished, 4, 20); vector<client> clients; vector<thread> client_threads; thread server_thread(&server::work, &local_server); (int = 0; < 4; i++) { clients.emplace_back(work_finished, updated[i], free_client_count,i); client_threads.emplace_back([&] { clients[i].work(); }); } server_thread.join(); (int = 0; < 4; i++) { client_threads[i].join(); } std::cout << "finaly" << std::endl; }
Comments
Post a Comment