What is a valid way to stop std :: stream on an external signal?

This is a code that does not work as described, please explain to me what is wrong here (the code is simplified to make it more readable).

shm_server server;

std::thread s{server};

// some work...

std::cout << "press any key to stop the server";
_getch();
server.stop();
s.join();

It looks like I'm calling a method stopfor another copy of the class shm_server. because it stop()only sets std::atomic_bool done;( shm_servermember) to true, but I see that the stream function (this operator()of shm_server) still sees doneequal false.

std::thread only has a moving contructor?

How to send a signal to the server in this typical case?

class shm_server {
    std::atomic_bool    done;
public:
    shm_server() : done{false} {}
    shm_server(shm_server& ) : done{false} {}
    void operator()() {
       while (!done) {
       //...
       }
    }
    void stop() {
       done = true;
    }
};
+4
source share
1 answer

- , shm_server . , , , , . . , const.

class shm_server  // cannot copy or move
{

  std::atomic_bool done_ {};

public:

  void
  operator()()
  {
    this->run();
  }

  void
  run()
  {
    using namespace std::chrono_literals;
    while (!this->done_.load())
      {
        std::clog << std::this_thread::get_id() << " working..." << std::endl;
        std::this_thread::sleep_for(1ms);
      }
  }

  void
  stop()
  {
    this->done_.store(true);
  }

};

. , .

- - run .

shm_server server {};
std::thread worker {server};  // won't compile

, , , server, .

@Ben Voigt server std::reference_wrapper, , .

shm_server server {};
std::thread worker {std::ref(server)};

std::thread, server.

, . , , - - server . std::thread .

shm_server server {};
std::thread worker {&shm_server::run, &server};

run server ( this) . run, . .

shm_server server {};
std::thread worker {&shm_server::operator(), &server};

.

int
main()
{
  using namespace std::chrono_literals;
  std::clog << std::this_thread::get_id() << " starting up" << std::endl;
  shm_server server {};
  std::thread worker {&shm_server::operator(), &server};
  //std::thread worker {std::ref(server)};                 // same effect
  //std::thread worker {&shm_server::run, &server};        // same effect
  std::this_thread::sleep_for(10ms);
  server.stop();
  worker.join();
  std::clog << std::this_thread::get_id() << " good bye" << std::endl;
}

:

140435324311360 starting up
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435306977024 working...
140435324311360 good bye

, shm_server , std::thread ( start member, ), .

#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>

class shm_server
{

  std::atomic_bool done_ {};
  std::thread worker_ {};

public:

  shm_server()
  {
    this->worker_ = std::thread {&shm_server::run_, this};
  }

  ~shm_server()
  {
    this->done_.store(true);
    if (this->worker_.joinable())
      this->worker_.join();
  }

private:

  void
  run_()
  {
    using namespace std::chrono_literals;
    while (!this->done_.load())
      {
        std::clog << std::this_thread::get_id() << " working..." << std::endl;
        std::this_thread::sleep_for(1ms);
      }
  }

};


int
main()
{
  using namespace std::chrono_literals;
  std::clog << std::this_thread::get_id() << " starting up" << std::endl;
  {
    shm_server server {};
    std::this_thread::sleep_for(10ms);
  }
  std::clog << std::this_thread::get_id() << " good bye" << std::endl;
}
+2

Source: https://habr.com/ru/post/1623345/


All Articles